From be3bf316c0e9f29cfe9c90e5dd7b903f88f54504 Mon Sep 17 00:00:00 2001 From: alexzorin Date: Fri, 20 Jan 2023 12:21:26 +1100 Subject: [PATCH 01/57] Deprecate {csr, keys} dirs & automatically truncate lineages (#9537) Based on my design [here](https://docs.google.com/document/d/1jGh_bZPnrhi96KzuIcyCJfnudl4m3pRPGkiK4fTo8e4/edit?usp=sharing). Fixes https://github.com/certbot/certbot/issues/4634 and https://github.com/certbot/certbot/issues/4635. - [x] Deprecate `NamespaceConfig.csr_dir`,`NamespaceConfig.key_dir`, ~~`constants.CSR_DIR` and `constants.KEY_DIR`~~. (`constants` is `_internal` so we can just delete it eventually). - [x] Update `certbot.crypto_util.generate_csr` and `.generate_key` to make `csr_dir` and `key_dir` optional, respectively. - [x] Change `certbot._internal.client.Client.obtain_certificate` to no longer include `csr_dir` and `key_dir` to the `.generate_csr` and `.generate_key` calls, respectively. - Automatically delete unwanted lineage items: - [x] In `certbot._internal.storage.RenewableCert`, add a function to truncate the lineage history according to the criteria (keep the current and the 5 prior certificates). - [x] Add a test suite for `truncate` - [x] In `certbot._internal.renewal.renew_cert`, call the lineage truncation function after the symlinks have been updated for the renewal. * Stop writing new files to /csr and /keys * storage: add lineage truncation * remove unused code * deprecate keys_dir and csr_dir * update CHANGELOG * just keep 5 prior certificates, dont be clever with expiry * docs: remove reference to /archive and /keys * filter {csr,key}_dir deprecations directly in tests --- .../certbot_tests/test_main.py | 23 ++++----- .../certbot_nginx/_internal/configurator.py | 1 + certbot/CHANGELOG.md | 5 +- certbot/certbot/_internal/client.py | 18 +++---- certbot/certbot/_internal/renewal.py | 1 + certbot/certbot/_internal/storage.py | 30 ++++++++++++ certbot/certbot/configuration.py | 5 ++ certbot/certbot/crypto_util.py | 48 ++++++++++--------- certbot/certbot/util.py | 17 +++++-- certbot/docs/using.rst | 4 -- certbot/tests/client_test.py | 24 ++++------ certbot/tests/configuration_test.py | 21 ++++---- certbot/tests/storage_test.py | 17 +++++++ 13 files changed, 135 insertions(+), 79 deletions(-) diff --git a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py index 65eca976d..356eaa774 100644 --- a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py +++ b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py @@ -329,7 +329,6 @@ def test_renew_with_changed_private_key_complexity(context: IntegrationTestsCont context.certbot(['renew', '--rsa-key-size', '2048']) - assert_cert_count_for_lineage(context.config_dir, certname, 3) key3 = join(context.config_dir, 'archive', certname, 'privkey3.pem') assert_rsa_key(key3, 2048) @@ -437,38 +436,37 @@ def test_reuse_key(context: IntegrationTestsContext) -> None: with open(join(context.config_dir, 'archive/{0}/privkey1.pem').format(certname), 'r') as file: privkey1 = file.read() + with open(join(context.config_dir, 'archive/{0}/cert1.pem').format(certname), 'r') as file: + cert1 = file.read() with open(join(context.config_dir, 'archive/{0}/privkey2.pem').format(certname), 'r') as file: privkey2 = file.read() + with open(join(context.config_dir, 'archive/{0}/cert2.pem').format(certname), 'r') as file: + cert2 = file.read() assert privkey1 == privkey2 context.certbot(['--cert-name', certname, '--domains', certname, '--force-renewal']) with open(join(context.config_dir, 'archive/{0}/privkey3.pem').format(certname), 'r') as file: privkey3 = file.read() + with open(join(context.config_dir, 'archive/{0}/cert3.pem').format(certname), 'r') as file: + cert3 = file.read() assert privkey2 != privkey3 context.certbot(['--cert-name', certname, '--domains', certname, '--reuse-key','--force-renewal']) - context.certbot(['renew', '--cert-name', certname, '--no-reuse-key', '--force-renewal']) - context.certbot(['renew', '--cert-name', certname, '--force-renewal']) - with open(join(context.config_dir, 'archive/{0}/privkey4.pem').format(certname), 'r') as file: privkey4 = file.read() + context.certbot(['renew', '--cert-name', certname, '--no-reuse-key', '--force-renewal']) with open(join(context.config_dir, 'archive/{0}/privkey5.pem').format(certname), 'r') as file: privkey5 = file.read() + context.certbot(['renew', '--cert-name', certname, '--force-renewal']) with open(join(context.config_dir, 'archive/{0}/privkey6.pem').format(certname), 'r') as file: privkey6 = file.read() + assert privkey3 == privkey4 assert privkey4 != privkey5 assert privkey5 != privkey6 - with open(join(context.config_dir, 'archive/{0}/cert1.pem').format(certname), 'r') as file: - cert1 = file.read() - with open(join(context.config_dir, 'archive/{0}/cert2.pem').format(certname), 'r') as file: - cert2 = file.read() - with open(join(context.config_dir, 'archive/{0}/cert3.pem').format(certname), 'r') as file: - cert3 = file.read() - assert len({cert1, cert2, cert3}) == 3 @@ -615,7 +613,6 @@ def test_renew_with_ec_keys(context: IntegrationTestsContext) -> None: # to the lineage key type, Certbot should keep the lineage key type. The curve will still # change to the default value, in order to stay consistent with the behavior of certonly. context.certbot(['certonly', '--force-renewal', '-d', certname]) - assert_cert_count_for_lineage(context.config_dir, certname, 3) key3 = join(context.config_dir, 'archive', certname, 'privkey3.pem') assert 200 < os.stat(key3).st_size < 250 # ec keys of 256 bits are ~225 bytes assert_elliptic_key(key3, SECP256R1) @@ -629,14 +626,12 @@ def test_renew_with_ec_keys(context: IntegrationTestsContext) -> None: context.certbot(['certonly', '--force-renewal', '-d', certname, '--key-type', 'rsa', '--cert-name', certname]) - assert_cert_count_for_lineage(context.config_dir, certname, 4) key4 = join(context.config_dir, 'archive', certname, 'privkey4.pem') assert_rsa_key(key4) # We expect that the previous behavior of requiring both --cert-name and # --key-type to be set to not apply to the renew subcommand. context.certbot(['renew', '--force-renewal', '--key-type', 'ecdsa']) - assert_cert_count_for_lineage(context.config_dir, certname, 5) key5 = join(context.config_dir, 'archive', certname, 'privkey5.pem') assert 200 < os.stat(key5).st_size < 250 # ec keys of 256 bits are ~225 bytes assert_elliptic_key(key5, SECP256R1) diff --git a/certbot-nginx/certbot_nginx/_internal/configurator.py b/certbot-nginx/certbot_nginx/_internal/configurator.py index b91b11a53..07243df2b 100644 --- a/certbot-nginx/certbot_nginx/_internal/configurator.py +++ b/certbot-nginx/certbot_nginx/_internal/configurator.py @@ -693,6 +693,7 @@ class NginxConfigurator(common.Configurator): le_key = crypto_util.generate_key( key_size=1024, key_dir=tmp_dir, keyname="key.pem", strict_permissions=self.config.strict_permissions) + assert le_key.file is not None key = OpenSSL.crypto.load_privatekey( OpenSSL.crypto.FILETYPE_PEM, le_key.pem) cert = acme_crypto_util.gen_ss_cert(key, domains=[socket.gethostname()]) diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index 25eaff6f2..387373fff 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -10,7 +10,10 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). ### Changed -* +* Certbot will no longer save previous CSRs and certificate private keys to `/etc/letsencrypt/csr` and `/etc/letsencrypt/keys`, respectively. These directories may be safely deleted. +* Certbot will now only keep the current and 5 previous certificates in the `/etc/letsencrypt/archive` directory for each certificate lineage. Any prior certificates will be automatically deleted upon renewal. This number may be further lowered in future releases. + * As always, users should only reference the certificate files within `/etc/letsencrypt/live` and never use `/etc/letsencrypt/archive` directly. See [Where are my certificates?](https://eff-certbot.readthedocs.io/en/stable/using.html#where-are-my-certificates) in the Certbot User Guide. +* `certbot.configuration.NamespaceConfig.key_dir` and `.csr_dir` are now deprecated. ### Fixed diff --git a/certbot/certbot/_internal/client.py b/certbot/certbot/_internal/client.py index 89c0e498a..1fe1df5ec 100644 --- a/certbot/certbot/_internal/client.py +++ b/certbot/certbot/_internal/client.py @@ -416,13 +416,13 @@ class Client: else: key = key or crypto_util.generate_key( key_size=key_size, - key_dir=self.config.key_dir, + key_dir=None, key_type=self.config.key_type, elliptic_curve=elliptic_curve, strict_permissions=self.config.strict_permissions, ) - csr = crypto_util.generate_csr(key, domains, self.config.csr_dir, - self.config.must_staple, self.config.strict_permissions) + csr = crypto_util.generate_csr( + key, domains, None, self.config.must_staple, self.config.strict_permissions) try: orderr = self._get_order_and_authorizations(csr.data, self.config.allow_subset_of_names) @@ -433,7 +433,7 @@ class Client: if self.config.allow_subset_of_names: successful_domains = self._successful_domains_from_error(error, domains) if successful_domains != domains and len(successful_domains) != 0: - return self._retry_obtain_certificate(key, csr, domains, successful_domains) + return self._retry_obtain_certificate(domains, successful_domains) raise authzr = orderr.authorizations auth_domains = {a.body.identifier.value for a in authzr} @@ -445,7 +445,7 @@ class Client: # domains contains a wildcard because the ACME spec forbids identifiers # in authzs from containing a wildcard character. if self.config.allow_subset_of_names and successful_domains != domains: - return self._retry_obtain_certificate(key, csr, domains, successful_domains) + return self._retry_obtain_certificate(domains, successful_domains) else: try: cert, chain = self.obtain_certificate_from_csr(csr, orderr) @@ -457,7 +457,7 @@ class Client: if self.config.allow_subset_of_names: successful_domains = self._successful_domains_from_error(error, domains) if successful_domains != domains and len(successful_domains) != 0: - return self._retry_obtain_certificate(key, csr, domains, successful_domains) + return self._retry_obtain_certificate(domains, successful_domains) raise def _get_order_and_authorizations(self, csr_pem: bytes, @@ -540,16 +540,12 @@ class Client: return successful_domains return [] - def _retry_obtain_certificate(self, key: util.Key, - csr: util.CSR, domains: List[str], successful_domains: List[str] + def _retry_obtain_certificate(self, domains: List[str], successful_domains: List[str] ) -> Tuple[bytes, bytes, util.Key, util.CSR]: failed_domains = [d for d in domains if d not in successful_domains] domains_list = ", ".join(failed_domains) display_util.notify("Unable to obtain a certificate with every requested " f"domain. Retrying without: {domains_list}") - if not self.config.dry_run: - os.remove(key.file) - os.remove(csr.file) return self.obtain_certificate(successful_domains) def _choose_lineagename(self, domains: List[str], certname: Optional[str]) -> str: diff --git a/certbot/certbot/_internal/renewal.py b/certbot/certbot/_internal/renewal.py index df5168ea2..ea5e0435f 100644 --- a/certbot/certbot/_internal/renewal.py +++ b/certbot/certbot/_internal/renewal.py @@ -392,6 +392,7 @@ def renew_cert(config: configuration.NamespaceConfig, domains: Optional[List[str # TODO: Check return value of save_successor lineage.save_successor(prior_version, new_cert, new_key.pem, new_chain, config) lineage.update_all_links_to(lineage.latest_common_version()) + lineage.truncate() hooks.renew_hook(config, domains, lineage.live_dir) diff --git a/certbot/certbot/_internal/storage.py b/certbot/certbot/_internal/storage.py index 978295cce..6c483734e 100644 --- a/certbot/certbot/_internal/storage.py +++ b/certbot/certbot/_internal/storage.py @@ -1,4 +1,5 @@ """Renewable certificates storage.""" +# pylint: disable=too-many-lines import datetime import glob import logging @@ -1243,3 +1244,32 @@ class RenewableCert(interfaces.RenewableCert): self.configuration = config_with_defaults(self.configfile) return target_version + + def truncate(self, num_prior_certs_to_keep: int = 5) -> None: + """Delete unused historical certificate, chain and key items from the lineage. + + A certificate version will be deleted if it is: + 1. not the current target, and + 2. not a previous version within num_prior_certs_to_keep. + + :param num_prior_certs_to_keep: How many prior certificate versions to keep. + + """ + # Do not want to delete the current or the previous num_prior_certs_to_keep certs + current_version = self.latest_common_version() + versions_to_delete = set(self.available_versions("cert")) + versions_to_delete -= set(range(current_version, + current_version - 1 - num_prior_certs_to_keep, -1)) + archive = self.archive_dir + + # Delete the remaining lineage items kinds for those certificate versions. + for ver in versions_to_delete: + logger.debug("Deleting %s/cert%d.pem and related items during clean up", + archive, ver) + for kind in ALL_FOUR: + item_path = os.path.join(archive, f"{kind}{ver}.pem") + try: + if os.path.exists(item_path): + os.unlink(item_path) + except OSError: + logger.debug("Failed to clean up %s", item_path, exc_info=True) diff --git a/certbot/certbot/configuration.py b/certbot/certbot/configuration.py index dd40a096f..9e0d3f9de 100644 --- a/certbot/certbot/configuration.py +++ b/certbot/certbot/configuration.py @@ -5,6 +5,7 @@ from typing import Any from typing import List from typing import Optional from urllib import parse +import warnings from certbot import errors from certbot import util @@ -150,6 +151,8 @@ class NamespaceConfig: @property def csr_dir(self) -> str: """Directory where new Certificate Signing Requests (CSRs) are saved.""" + warnings.warn("NamespaceConfig.csr_dir is deprecated and will be removed in an upcoming " + "release of Certbot", DeprecationWarning) return os.path.join(self.namespace.config_dir, constants.CSR_DIR) @property @@ -160,6 +163,8 @@ class NamespaceConfig: @property def key_dir(self) -> str: """Keys storage.""" + warnings.warn("NamespaceConfig.key_dir is deprecated and will be removed in an upcoming " + "release of Certbot", DeprecationWarning) return os.path.join(self.namespace.config_dir, constants.KEY_DIR) @property diff --git a/certbot/certbot/crypto_util.py b/certbot/certbot/crypto_util.py index a9a8269fe..4e95fd11b 100644 --- a/certbot/certbot/crypto_util.py +++ b/certbot/certbot/crypto_util.py @@ -51,7 +51,7 @@ logger = logging.getLogger(__name__) # High level functions -def generate_key(key_size: int, key_dir: str, key_type: str = "rsa", +def generate_key(key_size: int, key_dir: Optional[str], key_type: str = "rsa", elliptic_curve: str = "secp256r1", keyname: str = "key-certbot.pem", strict_permissions: bool = True) -> util.Key: """Initializes and saves a privkey. @@ -62,7 +62,7 @@ def generate_key(key_size: int, key_dir: str, key_type: str = "rsa", already exists at the path. :param int key_size: key size in bits if key size is rsa. - :param str key_dir: Key save directory. + :param str key_dir: Optional key save directory. :param str key_type: Key Type [rsa, ecdsa] :param str elliptic_curve: Name of the elliptic curve if key type is ecdsa. :param str keyname: Filename of key @@ -85,27 +85,29 @@ def generate_key(key_size: int, key_dir: str, key_type: str = "rsa", raise err # Save file - util.make_or_verify_dir(key_dir, 0o700, strict_permissions) - key_f, key_path = util.unique_file( - os.path.join(key_dir, keyname), 0o600, "wb") - with key_f: - key_f.write(key_pem) - if key_type == 'rsa': - logger.debug("Generating RSA key (%d bits): %s", key_size, key_path) - else: - logger.debug("Generating ECDSA key (%d bits): %s", key_size, key_path) + key_path = None + if key_dir: + util.make_or_verify_dir(key_dir, 0o700, strict_permissions) + key_f, key_path = util.unique_file( + os.path.join(key_dir, keyname), 0o600, "wb") + with key_f: + key_f.write(key_pem) + if key_type == 'rsa': + logger.debug("Generating RSA key (%d bits): %s", key_size, key_path) + else: + logger.debug("Generating ECDSA key (%d bits): %s", key_size, key_path) return util.Key(key_path, key_pem) -def generate_csr(privkey: util.Key, names: Union[List[str], Set[str]], path: str, +def generate_csr(privkey: util.Key, names: Union[List[str], Set[str]], path: Optional[str], must_staple: bool = False, strict_permissions: bool = True) -> util.CSR: """Initialize a CSR with the given private key. :param privkey: Key to include in the CSR :type privkey: :class:`certbot.util.Key` :param set names: `str` names to include in the CSR - :param str path: Certificate save directory. + :param str path: Optional certificate save directory. :param bool must_staple: If true, include the TLS Feature extension "OCSP Must-Staple" :param bool strict_permissions: If true and path exists, an exception is raised if the directory doesn't have 0755 permissions or isn't owned by the current user. @@ -117,13 +119,15 @@ def generate_csr(privkey: util.Key, names: Union[List[str], Set[str]], path: str csr_pem = acme_crypto_util.make_csr( privkey.pem, names, must_staple=must_staple) - # Save CSR - util.make_or_verify_dir(path, 0o755, strict_permissions) - csr_f, csr_filename = util.unique_file( - os.path.join(path, "csr-certbot.pem"), 0o644, "wb") - with csr_f: - csr_f.write(csr_pem) - logger.debug("Creating CSR: %s", csr_filename) + # Save CSR, if requested + csr_filename = None + if path: + util.make_or_verify_dir(path, 0o755, strict_permissions) + csr_f, csr_filename = util.unique_file( + os.path.join(path, "csr-certbot.pem"), 0o644, "wb") + with csr_f: + csr_f.write(csr_pem) + logger.debug("Creating CSR: %s", csr_filename) return util.CSR(csr_filename, csr_pem, "pem") @@ -254,10 +258,10 @@ def make_key(bits: int = 1024, key_type: str = "rsa", return crypto.dump_privatekey(crypto.FILETYPE_PEM, key) -def valid_privkey(privkey: str) -> bool: +def valid_privkey(privkey: Union[str, bytes]) -> bool: """Is valid RSA private key? - :param str privkey: Private key file contents in PEM + :param privkey: Private key file contents in PEM :returns: Validity of private key. :rtype: bool diff --git a/certbot/certbot/util.py b/certbot/certbot/util.py index 12507ef36..12427aa92 100644 --- a/certbot/certbot/util.py +++ b/certbot/certbot/util.py @@ -1,7 +1,6 @@ """Utilities for all Certbot.""" import argparse import atexit -import collections import errno import logging import platform @@ -14,6 +13,7 @@ from typing import Callable from typing import Dict from typing import IO from typing import List +from typing import NamedTuple from typing import Optional from typing import Set from typing import Tuple @@ -35,9 +35,18 @@ if _USE_DISTRO: logger = logging.getLogger(__name__) -Key = collections.namedtuple("Key", "file pem") -# Note: form is the type of data, "pem" or "der" -CSR = collections.namedtuple("CSR", "file data form") +class Key(NamedTuple): + """Container for an optional file path and contents for a PEM-formated private key.""" + file: Optional[str] + pem: bytes + + +class CSR(NamedTuple): + """Container for an optional file path and contents for a PEM or DER-formatted CSR.""" + file: Optional[str] + data: bytes + # Note: form is the type of data, "pem" or "der" + form: str # ANSI SGR escape codes diff --git a/certbot/docs/using.rst b/certbot/docs/using.rst index add692e73..359119f0c 100644 --- a/certbot/docs/using.rst +++ b/certbot/docs/using.rst @@ -879,10 +879,6 @@ private key file, you will also need to use ``chgrp`` and ``chmod 0640`` to allow the server to read ``/etc/letsencrypt/live/$domain/privkey.pem``. -.. note:: ``/etc/letsencrypt/archive`` and ``/etc/letsencrypt/keys`` - contain all previous keys and certificates, while - ``/etc/letsencrypt/live`` symlinks to the latest versions. - The following files are available: ``privkey.pem`` diff --git a/certbot/tests/client_test.py b/certbot/tests/client_test.py index 6b430831f..cb16890d3 100644 --- a/certbot/tests/client_test.py +++ b/certbot/tests/client_test.py @@ -373,19 +373,18 @@ class ClientTest(ClientTestCommon): mock_crypto_util.generate_key.assert_called_once_with( key_size=self.config.rsa_key_size, - key_dir=self.config.key_dir, + key_dir=None, key_type=self.config.key_type, elliptic_curve="secp256r1", strict_permissions=True, ) mock_crypto_util.generate_csr.assert_called_once_with( - mock.sentinel.key, self.eg_domains, self.config.csr_dir, False, True) + mock.sentinel.key, self.eg_domains, None, False, True) mock_crypto_util.cert_and_chain_from_fullchain.assert_called_once_with( self.eg_order.fullchain_pem) @mock.patch("certbot._internal.client.crypto_util") - @mock.patch("certbot.compat.os.remove") - def test_obtain_certificate_partial_success(self, mock_remove, mock_crypto_util): + def test_obtain_certificate_partial_success(self, mock_crypto_util): csr = util.CSR(form="pem", file=mock.sentinel.csr_file, data=CSR_SAN) key = util.CSR(form="pem", file=mock.sentinel.key_file, data=CSR_SAN) mock_crypto_util.generate_csr.return_value = csr @@ -398,12 +397,10 @@ class ClientTest(ClientTestCommon): self.assertEqual(mock_crypto_util.generate_key.call_count, 2) self.assertEqual(mock_crypto_util.generate_csr.call_count, 2) - self.assertEqual(mock_remove.call_count, 2) self.assertEqual(mock_crypto_util.cert_and_chain_from_fullchain.call_count, 1) @mock.patch("certbot._internal.client.crypto_util") - @mock.patch("certbot.compat.os.remove") - def test_obtain_certificate_finalize_order_partial_success(self, mock_remove, mock_crypto_util): + def test_obtain_certificate_finalize_order_partial_success(self, mock_crypto_util): from acme import messages csr = util.CSR(form="pem", file=mock.sentinel.csr_file, data=CSR_SAN) key = util.CSR(form="pem", file=mock.sentinel.key_file, data=CSR_SAN) @@ -435,9 +432,8 @@ class ClientTest(ClientTestCommon): successful_domains = [d for d in self.eg_domains if d != 'example.com'] self.assertEqual(mock_crypto_util.generate_key.call_count, 2) mock_crypto_util.generate_csr.assert_has_calls([ - mock.call(key, self.eg_domains, self.config.csr_dir, self.config.must_staple, self.config.strict_permissions), - mock.call(key, successful_domains, self.config.csr_dir, self.config.must_staple, self.config.strict_permissions)]) - self.assertEqual(mock_remove.call_count, 2) + mock.call(key, self.eg_domains, None, self.config.must_staple, self.config.strict_permissions), + mock.call(key, successful_domains, None, self.config.must_staple, self.config.strict_permissions)]) self.assertEqual(mock_crypto_util.cert_and_chain_from_fullchain.call_count, 1) @mock.patch("certbot._internal.client.crypto_util") @@ -496,8 +492,7 @@ class ClientTest(ClientTestCommon): self.assertEqual(mock_crypto_util.cert_and_chain_from_fullchain.call_count, 0) @mock.patch("certbot._internal.client.crypto_util") - @mock.patch("certbot.compat.os.remove") - def test_obtain_certificate_get_order_partial_success(self, mock_remove, mock_crypto_util): + def test_obtain_certificate_get_order_partial_success(self, mock_crypto_util): from acme import messages csr = util.CSR(form="pem", file=mock.sentinel.csr_file, data=CSR_SAN) key = util.CSR(form="pem", file=mock.sentinel.key_file, data=CSR_SAN) @@ -529,9 +524,8 @@ class ClientTest(ClientTestCommon): successful_domains = [d for d in self.eg_domains if d != 'example.com'] self.assertEqual(mock_crypto_util.generate_key.call_count, 2) mock_crypto_util.generate_csr.assert_has_calls([ - mock.call(key, self.eg_domains, self.config.csr_dir, self.config.must_staple, self.config.strict_permissions), - mock.call(key, successful_domains, self.config.csr_dir, self.config.must_staple, self.config.strict_permissions)]) - self.assertEqual(mock_remove.call_count, 2) + mock.call(key, self.eg_domains, None, self.config.must_staple, self.config.strict_permissions), + mock.call(key, successful_domains, None, self.config.must_staple, self.config.strict_permissions)]) self.assertEqual(mock_crypto_util.cert_and_chain_from_fullchain.call_count, 1) @mock.patch("certbot._internal.client.crypto_util") diff --git a/certbot/tests/configuration_test.py b/certbot/tests/configuration_test.py index 61c902bc9..22060a688 100644 --- a/certbot/tests/configuration_test.py +++ b/certbot/tests/configuration_test.py @@ -1,6 +1,7 @@ """Tests for certbot.configuration.""" import unittest from unittest import mock +import warnings from certbot import errors from certbot._internal import constants @@ -55,15 +56,17 @@ class NamespaceConfigTest(test_util.ConfigTestCase): self.assertEqual( os.path.normpath(self.config.backup_dir), os.path.normpath(os.path.join(self.config.work_dir, 'backups'))) - self.assertEqual( - os.path.normpath(self.config.csr_dir), - os.path.normpath(os.path.join(self.config.config_dir, 'csr'))) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + self.assertEqual( + os.path.normpath(self.config.csr_dir), + os.path.normpath(os.path.join(self.config.config_dir, 'csr'))) + self.assertEqual( + os.path.normpath(self.config.key_dir), + os.path.normpath(os.path.join(self.config.config_dir, 'keys'))) self.assertEqual( os.path.normpath(self.config.in_progress_dir), os.path.normpath(os.path.join(self.config.work_dir, '../p'))) - self.assertEqual( - os.path.normpath(self.config.key_dir), - os.path.normpath(os.path.join(self.config.config_dir, 'keys'))) self.assertEqual( os.path.normpath(self.config.temp_checkpoint_dir), os.path.normpath(os.path.join(self.config.work_dir, 't'))) @@ -97,9 +100,11 @@ class NamespaceConfigTest(test_util.ConfigTestCase): os.path.join(os.getcwd(), logs_base)) self.assertTrue(os.path.isabs(config.accounts_dir)) self.assertTrue(os.path.isabs(config.backup_dir)) - self.assertTrue(os.path.isabs(config.csr_dir)) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + self.assertTrue(os.path.isabs(config.csr_dir)) + self.assertTrue(os.path.isabs(config.key_dir)) self.assertTrue(os.path.isabs(config.in_progress_dir)) - self.assertTrue(os.path.isabs(config.key_dir)) self.assertTrue(os.path.isabs(config.temp_checkpoint_dir)) @mock.patch('certbot.configuration.constants') diff --git a/certbot/tests/storage_test.py b/certbot/tests/storage_test.py index 3a1f2b7b4..13c2be0a5 100644 --- a/certbot/tests/storage_test.py +++ b/certbot/tests/storage_test.py @@ -839,6 +839,23 @@ class RenewableCertTests(BaseRenewableCertTest): storage.RenewableCert(self.config_file.filename, self.config, update_symlinks=True) + def test_truncate(self): + # It should not do anything when there's less than 5 cert history + for kind in ALL_FOUR: + self._write_out_kind(kind, 1) + with mock.patch('certbot.compat.os.unlink') as mock_unlink: + self.test_rc.truncate() + mock_unlink.assert_not_called() + + # It should truncate the excess when there's more than 5 cert history + for kind in ALL_FOUR: + for i in range(2, 8): + self._write_out_kind(kind, i) + with mock.patch('certbot.compat.os.unlink') as mock_unlink: + self.test_rc.truncate() + self.assertEqual(mock_unlink.call_count, 1 * len(ALL_FOUR)) + self.assertIn("1.pem", mock_unlink.call_args_list[0][0][0]) + class DeleteFilesTest(BaseRenewableCertTest): """Tests for certbot._internal.storage.delete_files""" def setUp(self): From 6505054f622f2621af4be58760a96cdc0d1f6bd9 Mon Sep 17 00:00:00 2001 From: Alex Zorin Date: Mon, 23 Jan 2023 18:36:34 +1100 Subject: [PATCH 02/57] account: stop storing legacy new_authzr_uri --- certbot/certbot/_internal/account.py | 29 +++------------------------- certbot/tests/account_test.py | 11 +---------- 2 files changed, 4 insertions(+), 36 deletions(-) diff --git a/certbot/certbot/_internal/account.py b/certbot/certbot/_internal/account.py index eb2466f32..8dcf1de09 100644 --- a/certbot/certbot/_internal/account.py +++ b/certbot/certbot/_internal/account.py @@ -126,18 +126,6 @@ class AccountMemoryStorage(interfaces.AccountStorage): raise errors.AccountNotFound(account_id) -class RegistrationResourceWithNewAuthzrURI(messages.RegistrationResource): - """A backwards-compatible RegistrationResource with a new-authz URI. - - Hack: Certbot versions pre-0.11.1 expect to load - new_authzr_uri as part of the account. Because people - sometimes switch between old and new versions, we will - continue to write out this field for some time so older - clients don't crash in that scenario. - """ - new_authzr_uri: str = jose.field('new_authzr_uri') - - class AccountFileStorage(interfaces.AccountStorage): """Accounts file storage. @@ -360,20 +348,9 @@ class AccountFileStorage(interfaces.AccountStorage): def _update_regr(self, account: Account, acme: ClientV2, dir_path: str) -> None: with open(self._regr_path(dir_path), "w") as regr_file: - regr = account.regr - # If we have a value for new-authz, save it for forwards - # compatibility with older versions of Certbot. If we don't - # have a value for new-authz, this is an ACMEv2 directory where - # an older version of Certbot won't work anyway. - if hasattr(acme.directory, "new-authz"): - regr = RegistrationResourceWithNewAuthzrURI( - new_authzr_uri=acme.directory.new_authz, - body={}, - uri=regr.uri) - else: - regr = messages.RegistrationResource( - body={}, - uri=regr.uri) + regr = messages.RegistrationResource( + body={}, + uri=account.regr.uri) regr_file.write(regr.json_dumps()) def _update_meta(self, account: Account, dir_path: str) -> None: diff --git a/certbot/tests/account_test.py b/certbot/tests/account_test.py index 0037de31e..e0972f247 100644 --- a/certbot/tests/account_test.py +++ b/certbot/tests/account_test.py @@ -116,8 +116,7 @@ class AccountFileStorageTest(test_util.ConfigTestCase): 2021, 1, 5, 14, 4, 10, tzinfo=pytz.UTC)) self.acc = Account( regr=messages.RegistrationResource( - uri=None, body=messages.Registration(), - new_authzr_uri=new_authzr_uri), + uri=None, body=messages.Registration()), key=KEY, meta=meta) self.mock_client = mock.MagicMock() @@ -141,14 +140,6 @@ class AccountFileStorageTest(test_util.ConfigTestCase): loaded = self.storage.load(self.acc.id) self.assertEqual(self.acc, loaded) - def test_save_and_restore_old_version(self): - """Saved regr should include a new_authzr_uri for older Certbots""" - self.storage.save(self.acc, self.mock_client) - path = os.path.join(self.config.accounts_dir, self.acc.id, "regr.json") - with open(path, "r") as f: - regr = json.load(f) - self.assertIn("new_authzr_uri", regr) - def test_update_regr(self): self.storage.update_regr(self.acc, self.mock_client) account_path = os.path.join(self.config.accounts_dir, self.acc.id) From 554143e1870104974ee12b670cf1cbf4a41e513b Mon Sep 17 00:00:00 2001 From: Alex Zorin Date: Mon, 23 Jan 2023 19:43:34 +1100 Subject: [PATCH 03/57] fix lint --- certbot/CHANGELOG.md | 2 +- certbot/certbot/_internal/account.py | 8 ++++---- certbot/certbot/_internal/main.py | 2 +- certbot/tests/account_test.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index 387373fff..cc7e5e78f 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -17,7 +17,7 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). ### Fixed -* +* Fixed a crash when registering an account with BuyPass' ACME server. More details about these changes can be found on our GitHub repo. diff --git a/certbot/certbot/_internal/account.py b/certbot/certbot/_internal/account.py index 8dcf1de09..e289245b1 100644 --- a/certbot/certbot/_internal/account.py +++ b/certbot/certbot/_internal/account.py @@ -242,11 +242,11 @@ class AccountFileStorage(interfaces.AccountStorage): dir_path = self._prepare(account) self._create(account, dir_path) self._update_meta(account, dir_path) - self._update_regr(account, client, dir_path) + self._update_regr(account, dir_path) except IOError as error: raise errors.AccountStorageError(error) - def update_regr(self, account: Account, client: ClientV2) -> None: + def update_regr(self, account: Account) -> None: """Update the registration resource. :param Account account: account to update @@ -255,7 +255,7 @@ class AccountFileStorage(interfaces.AccountStorage): """ try: dir_path = self._prepare(account) - self._update_regr(account, client, dir_path) + self._update_regr(account, dir_path) except IOError as error: raise errors.AccountStorageError(error) @@ -346,7 +346,7 @@ class AccountFileStorage(interfaces.AccountStorage): with util.safe_open(self._key_path(dir_path), "w", chmod=0o400) as key_file: key_file.write(account.key.json_dumps()) - def _update_regr(self, account: Account, acme: ClientV2, dir_path: str) -> None: + def _update_regr(self, account: Account, dir_path: str) -> None: with open(self._regr_path(dir_path), "w") as regr_file: regr = messages.RegistrationResource( body={}, diff --git a/certbot/certbot/_internal/main.py b/certbot/certbot/_internal/main.py index 0712f1962..316503c5d 100644 --- a/certbot/certbot/_internal/main.py +++ b/certbot/certbot/_internal/main.py @@ -948,7 +948,7 @@ def update_account(config: configuration.NamespaceConfig, # the v2 uri. Since it's the same object on disk, put it back to the v1 uri # so that we can also continue to use the account object with acmev1. acc.regr = acc.regr.update(uri=prev_regr_uri) - account_storage.update_regr(acc, cb_client.acme) + account_storage.update_regr(acc) if not config.email: display_util.notify("Any contact information associated " diff --git a/certbot/tests/account_test.py b/certbot/tests/account_test.py index e0972f247..f00ac363d 100644 --- a/certbot/tests/account_test.py +++ b/certbot/tests/account_test.py @@ -141,7 +141,7 @@ class AccountFileStorageTest(test_util.ConfigTestCase): self.assertEqual(self.acc, loaded) def test_update_regr(self): - self.storage.update_regr(self.acc, self.mock_client) + self.storage.update_regr(self.acc) account_path = os.path.join(self.config.accounts_dir, self.acc.id) self.assertTrue(os.path.exists(account_path)) self.assertTrue(os.path.exists(os.path.join(account_path, "regr.json"))) From 613e698199e8c81dda07932c12efaf5a77558e0d Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 24 Jan 2023 13:05:01 -0800 Subject: [PATCH 04/57] disable random sleep in lock_test.py (#9545) --- tests/lock_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lock_test.py b/tests/lock_test.py index a1e706c2f..09e11b25f 100644 --- a/tests/lock_test.py +++ b/tests/lock_test.py @@ -134,7 +134,7 @@ def set_up_command(config_dir: str, logs_dir: str, work_dir: str, nginx_dir: str return ( 'certbot --cert-path {0} --key-path {1} --config-dir {2} ' '--logs-dir {3} --work-dir {4} --nginx-server-root {5} --debug ' - '--force-renewal --nginx -vv '.format( + '--force-renewal --nginx -vv --no-random-sleep-on-renew '.format( test_util.vector_path('cert.pem'), test_util.vector_path('rsa512_key.pem'), config_dir, logs_dir, work_dir, nginx_dir).split()) From 81ff6fcc0d1460d669d516dc4df6d90c39507cfa Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Tue, 24 Jan 2023 14:06:53 -0800 Subject: [PATCH 05/57] acme.messages.Error: add mutability (#9546) * acme.messages.Error: add mutability As of Python 3.11, an exception caught within a `with` statement will update the __traceback__ attribute. Because acme.messages.Error was immutable, this was causing a knock-on exception, causing certbot to exit abnormally. This commit hacks in mutability for acme.messages.Error Fixes #9539 * Add CHANGELOG entry --- acme/acme/messages.py | 7 +++++++ acme/tests/messages_test.py | 17 +++++++++++++++++ certbot/CHANGELOG.md | 2 +- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/acme/acme/messages.py b/acme/acme/messages.py index 0e02a054e..c1af1991a 100644 --- a/acme/acme/messages.py +++ b/acme/acme/messages.py @@ -123,6 +123,9 @@ class Error(jose.JSONObjectWithFields, errors.Error): https://datatracker.ietf.org/doc/html/rfc7807 + Note: Although Error inherits from JSONObjectWithFields, which is immutable, + we add mutability for Error to comply with the Python exception API. + :ivar str typ: :ivar str title: :ivar str detail: @@ -185,6 +188,10 @@ class Error(jose.JSONObjectWithFields, errors.Error): return code return None + # Hack to allow mutability on Errors (see GH #9539) + def __setattr__(self, name: str, value: Any) -> None: + return object.__setattr__(self, name, value) + def __str__(self) -> str: result = b' :: '.join( part.encode('ascii', 'backslashreplace') for part in diff --git a/acme/tests/messages_test.py b/acme/tests/messages_test.py index cbff65771..7d70822a8 100644 --- a/acme/tests/messages_test.py +++ b/acme/tests/messages_test.py @@ -1,6 +1,7 @@ """Tests for acme.messages.""" from typing import Dict import unittest +import contextlib from unittest import mock import warnings @@ -91,6 +92,22 @@ class ErrorTest(unittest.TestCase): u"Problem for {1.identifier.value}: {1.typ} :: {1.description} :: {1.detail} :: {1.title}").format( self.error_with_subproblems, self.subproblem)) + # this test is based on a minimal reproduction of a contextmanager/immutable + # exception related error: https://github.com/python/cpython/issues/99856 + def test_with_context_manager(self): + from acme.messages import Error + + @contextlib.contextmanager + def context(): + yield + + try: + with context(): + raise self.error_custom + except Error as e: + self.assertIsNotNone(self.error_custom.__traceback__) + + class ConstantTest(unittest.TestCase): """Tests for acme.messages._Constant.""" diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index 387373fff..763425f2d 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -17,7 +17,7 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). ### Fixed -* +* Fixed a bug where Certbot would crash with `AttributeError: can't set attribute` on ACME server errors in Python 3.11. See [GH #9539](https://github.com/certbot/certbot/issues/9539). More details about these changes can be found on our GitHub repo. From 4ad71ab5ae78b0a7698d983cc588d91be11c5768 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 24 Jan 2023 17:00:06 -0800 Subject: [PATCH 06/57] Fix tox environments (#9547) * fix cover tox envs * make test work on all Pythons * Remove unused import Co-authored-by: alexzorin Co-authored-by: alexzorin --- .../templates/jobs/standard-tests-jobs.yml | 8 ++++---- acme/tests/messages_test.py | 17 +++++++---------- certbot/docs/contributing.rst | 2 +- tox.ini | 2 +- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml index c49e22bc1..1e6d7a352 100644 --- a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml +++ b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml @@ -7,10 +7,10 @@ jobs: macos-py37-cover: IMAGE_NAME: macOS-12 PYTHON_VERSION: 3.7 - TOXENV: py37-cover + TOXENV: cover macos-cover: IMAGE_NAME: macOS-12 - TOXENV: py3-cover + TOXENV: cover windows-py37: IMAGE_NAME: windows-2019 PYTHON_VERSION: 3.7 @@ -18,7 +18,7 @@ jobs: windows-py39-cover: IMAGE_NAME: windows-2019 PYTHON_VERSION: 3.9 - TOXENV: py39-cover-win + TOXENV: cover-win windows-integration-certbot: IMAGE_NAME: windows-2019 PYTHON_VERSION: 3.9 @@ -37,7 +37,7 @@ jobs: TOXENV: py37 linux-cover: IMAGE_NAME: ubuntu-22.04 - TOXENV: py3-cover + TOXENV: cover linux-lint: IMAGE_NAME: ubuntu-22.04 TOXENV: lint-posix diff --git a/acme/tests/messages_test.py b/acme/tests/messages_test.py index 7d70822a8..405e801a2 100644 --- a/acme/tests/messages_test.py +++ b/acme/tests/messages_test.py @@ -94,18 +94,15 @@ class ErrorTest(unittest.TestCase): # this test is based on a minimal reproduction of a contextmanager/immutable # exception related error: https://github.com/python/cpython/issues/99856 - def test_with_context_manager(self): - from acme.messages import Error - - @contextlib.contextmanager - def context(): - yield + def test_setting_traceback(self): + self.assertIsNone(self.error_custom.__traceback__) try: - with context(): - raise self.error_custom - except Error as e: - self.assertIsNotNone(self.error_custom.__traceback__) + 1/0 + except ZeroDivisionError as e: + self.error_custom.__traceback__ = e.__traceback__ + + self.assertIsNotNone(self.error_custom.__traceback__) class ConstantTest(unittest.TestCase): diff --git a/certbot/docs/contributing.rst b/certbot/docs/contributing.rst index 6d1faf061..49cc1fc81 100644 --- a/certbot/docs/contributing.rst +++ b/certbot/docs/contributing.rst @@ -130,7 +130,7 @@ For debugging, we recommend putting Once you are done with your code changes, and the tests in ``foo_test.py`` pass, run all of the unit tests for Certbot and check for coverage with ``tox --e py3-cover``. You should then check for code style with ``tox -e lint`` (all +-e cover``. You should then check for code style with ``tox -e lint`` (all files) or ``pylint --rcfile=.pylintrc path/to/file.py`` (single file at a time). diff --git a/tox.ini b/tox.ini index a3436e95a..2bdd5e25c 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ [tox] skipsdist = true -envlist = {py3-cover,lint,mypy}-{win,posix} +envlist = {cover,lint,mypy}-{win,posix} [base] # pip installs the requested packages in editable mode From c79a5d440747a75b3e10ce95e5b4e5b265c67826 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 25 Jan 2023 13:15:51 -0800 Subject: [PATCH 07/57] Start sending coverage data to codecov (#9544) * set up codecov * export coverage data to xml --- .azure-pipelines/main.yml | 6 +++-- .../templates/jobs/standard-tests-jobs.yml | 5 ++++ .../templates/steps/tox-steps.yml | 25 +++++++++++++++++++ .github/codecov.yml | 7 ++++++ 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 .github/codecov.yml diff --git a/.azure-pipelines/main.yml b/.azure-pipelines/main.yml index cae4f799c..d3c3a152e 100644 --- a/.azure-pipelines/main.yml +++ b/.azure-pipelines/main.yml @@ -1,8 +1,10 @@ -trigger: none +# We run the test suite on commits to master so codecov gets coverage data +# about the master branch and can use it to track coverage changes. +trigger: + - master pr: - master - '*.x' jobs: - template: templates/jobs/standard-tests-jobs.yml - diff --git a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml index 1e6d7a352..5d0044d19 100644 --- a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml +++ b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml @@ -11,6 +11,7 @@ jobs: macos-cover: IMAGE_NAME: macOS-12 TOXENV: cover + UPLOAD_COVERAGE: 1 windows-py37: IMAGE_NAME: windows-2019 PYTHON_VERSION: 3.7 @@ -19,10 +20,12 @@ jobs: IMAGE_NAME: windows-2019 PYTHON_VERSION: 3.9 TOXENV: cover-win + UPLOAD_COVERAGE: 1 windows-integration-certbot: IMAGE_NAME: windows-2019 PYTHON_VERSION: 3.9 TOXENV: integration-certbot + UPLOAD_COVERAGE: 1 linux-oldest-tests-1: IMAGE_NAME: ubuntu-22.04 PYTHON_VERSION: 3.7 @@ -38,6 +41,7 @@ jobs: linux-cover: IMAGE_NAME: ubuntu-22.04 TOXENV: cover + UPLOAD_COVERAGE: 1 linux-lint: IMAGE_NAME: ubuntu-22.04 TOXENV: lint-posix @@ -49,6 +53,7 @@ jobs: PYTHON_VERSION: 3.8 TOXENV: integration ACME_SERVER: pebble + UPLOAD_COVERAGE: 1 apache-compat: IMAGE_NAME: ubuntu-22.04 TOXENV: apache_compat diff --git a/.azure-pipelines/templates/steps/tox-steps.yml b/.azure-pipelines/templates/steps/tox-steps.yml index fbda960a5..a85e1519a 100644 --- a/.azure-pipelines/templates/steps/tox-steps.yml +++ b/.azure-pipelines/templates/steps/tox-steps.yml @@ -55,3 +55,28 @@ steps: AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) AWS_EC2_PEM_FILE: $(testFarmPem.secureFilePath) displayName: Run tox + # For now, let's omit `set -e` and avoid the script exiting with a nonzero + # status code to prevent problems here from causing build failures. If + # this turns out to work well, we can change this. + - bash: | + python3 tools/pip_install.py -I coverage + case "$AGENT_OS" in + Darwin) + CODECOV_URL="https://uploader.codecov.io/latest/macos/codecov" + ;; + Linux) + CODECOV_URL="https://uploader.codecov.io/latest/linux/codecov" + ;; + Windows_NT) + CODECOV_URL="https://uploader.codecov.io/latest/windows/codecov.exe" + ;; + *) + echo "Unexpected OS" + exit 0 + esac + curl --retry 3 -o codecov "$CODECOV_URL" + chmod +x codecov + coverage xml + ./codecov || echo "Uploading coverage data failed" + condition: ne(variables['UPLOAD_COVERAGE'], '') + displayName: Upload coverage data diff --git a/.github/codecov.yml b/.github/codecov.yml new file mode 100644 index 000000000..23d2fbbe9 --- /dev/null +++ b/.github/codecov.yml @@ -0,0 +1,7 @@ +# This disables all reporting from codecov. Let's just set it up to collect +# data for now and then we can play with the settings here. +comment: false +coverage: + status: + project: off + patch: off From b0748b69e77f7d4058472feb8d61f94ffa8ff7ac Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Wed, 25 Jan 2023 15:59:22 -0800 Subject: [PATCH 08/57] Replace probot/stale app with a Github Action (#9466) * Replace probot/stale app with a Github Action This creates a Github Actions workflow which seems to be the supported way of automarking issues as stale. Adds a dry-run flag to test it out. * small fixups * cron typo * disable unnecessary permissions * use friendlier name --- .github/stale.yml | 35 ------------------------------- .github/workflows/stale.yml | 42 +++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 35 deletions(-) delete mode 100644 .github/stale.yml create mode 100644 .github/workflows/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml deleted file mode 100644 index 2e4106314..000000000 --- a/.github/stale.yml +++ /dev/null @@ -1,35 +0,0 @@ -# Configuration for https://github.com/marketplace/stale - -# Number of days of inactivity before an Issue or Pull Request becomes stale -daysUntilStale: 365 - -# Number of days of inactivity before an Issue or Pull Request with the stale label is closed. -# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. -# When changing this value, be sure to also update markComment below. -daysUntilClose: 30 - -# Ignore issues with an assignee (defaults to false) -exemptAssignees: true - -# Label to use when marking as stale -staleLabel: needs-update - -# Comment to post when marking as stale. Set to `false` to disable -markComment: > - We've made a lot of changes to Certbot since this issue was opened. If you - still have this issue with an up-to-date version of Certbot, can you please - add a comment letting us know? This helps us to better see what issues are - still affecting our users. If there is no activity in the next 30 days, this - issue will be automatically closed. - -# Comment to post when closing a stale Issue or Pull Request. -closeComment: > - This issue has been closed due to lack of activity, but if you think it - should be reopened, please open a new issue with a link to this one and we'll - take a look. - -# Limit the number of actions per hour, from 1-30. Default is 30 -limitPerRun: 1 - -# Don't mark pull requests as stale. -only: issues diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 000000000..010259922 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,42 @@ +name: Update Stale Issues +on: + schedule: + # Run at midnight every night + - cron: '24 1 * * *' +permissions: + issues: write +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v6 + with: + # REMOVEME: dry run to see if this works + debug-only: true + + # Idle number of days before marking issues stale + days-before-issue-stale: 365 + + # Idle number of days before closing stale issues + days-before-issue-close: 30 + + # Ignore issues with an assignee + exempt-all-issue-assignees: true + + # Label to use when marking as stale + stale-issue-label: needs-update + + stale-issue-message: > + We've made a lot of changes to Certbot since this issue was opened. If you + still have this issue with an up-to-date version of Certbot, can you please + add a comment letting us know? This helps us to better see what issues are + still affecting our users. If there is no activity in the next 30 days, this + issue will be automatically closed. + + close-issue-message: > + This issue has been closed due to lack of activity, but if you think it + should be reopened, please open a new issue with a link to this one and we'll + take a look. + + # Limit the number of actions per hour, from 1-30. Default is 30 + operations-per-run: 1 From 2e3cace73947d6b4f89e61571a0aff5d6e83a764 Mon Sep 17 00:00:00 2001 From: Alex Zorin Date: Fri, 27 Jan 2023 10:38:00 +1100 Subject: [PATCH 09/57] remove docstring for removed argument --- certbot/certbot/_internal/account.py | 1 - 1 file changed, 1 deletion(-) diff --git a/certbot/certbot/_internal/account.py b/certbot/certbot/_internal/account.py index e289245b1..9c8146b63 100644 --- a/certbot/certbot/_internal/account.py +++ b/certbot/certbot/_internal/account.py @@ -250,7 +250,6 @@ class AccountFileStorage(interfaces.AccountStorage): """Update the registration resource. :param Account account: account to update - :param ClientV2 client: ACME client associated to the account """ try: From 08e008ac54381b07bfeefc8dd72b11577639e758 Mon Sep 17 00:00:00 2001 From: Alex Zorin Date: Fri, 27 Jan 2023 10:41:45 +1100 Subject: [PATCH 10/57] remove unused attributes from test --- certbot/tests/account_test.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/certbot/tests/account_test.py b/certbot/tests/account_test.py index f00ac363d..3daac6498 100644 --- a/certbot/tests/account_test.py +++ b/certbot/tests/account_test.py @@ -109,7 +109,6 @@ class AccountFileStorageTest(test_util.ConfigTestCase): self.storage = AccountFileStorage(self.config) from certbot._internal.account import Account - new_authzr_uri = "hi" meta = Account.Meta( creation_host="test.example.org", creation_dt=datetime.datetime( @@ -120,7 +119,6 @@ class AccountFileStorageTest(test_util.ConfigTestCase): key=KEY, meta=meta) self.mock_client = mock.MagicMock() - self.mock_client.directory.new_authz = new_authzr_uri def test_init_creates_dir(self): self.assertTrue(os.path.isdir( From f0b6ba072f8be832d02ad7c8d0ca349891b1bb7f Mon Sep 17 00:00:00 2001 From: alexzorin Date: Fri, 27 Jan 2023 14:44:17 +1100 Subject: [PATCH 11/57] certbot-ci: boulder only supports port 80 for http-01 (#9548) * certbot-ci: boulder will now only supports port 80 for http-01 * forgot to actually use the http_01_port argument * print the port the proxy listens on * try allow binding to privileged ports --- .azure-pipelines/templates/steps/tox-steps.yml | 1 + .../utils/acme_server.py | 18 ++++++++++-------- .../utils/constants.py | 1 + 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.azure-pipelines/templates/steps/tox-steps.yml b/.azure-pipelines/templates/steps/tox-steps.yml index a85e1519a..ae8a2c56b 100644 --- a/.azure-pipelines/templates/steps/tox-steps.yml +++ b/.azure-pipelines/templates/steps/tox-steps.yml @@ -21,6 +21,7 @@ steps: nginx-light \ openssl sudo systemctl stop nginx + sudo sysctl net.ipv4.ip_unprivileged_port_start=0 condition: startswith(variables['IMAGE_NAME'], 'ubuntu') displayName: Install Linux dependencies - task: UsePythonVersion@0 diff --git a/certbot-ci/certbot_integration_tests/utils/acme_server.py b/certbot-ci/certbot_integration_tests/utils/acme_server.py index ecd7fe778..b75c412d5 100755 --- a/certbot-ci/certbot_integration_tests/utils/acme_server.py +++ b/certbot-ci/certbot_integration_tests/utils/acme_server.py @@ -44,7 +44,7 @@ class ACMEServer: """ def __init__(self, acme_server: str, nodes: List[str], http_proxy: bool = True, stdout: bool = False, dns_server: Optional[str] = None, - http_01_port: int = DEFAULT_HTTP_01_PORT) -> None: + http_01_port: Optional[int] = None) -> None: """ Create an ACMEServer instance. :param str acme_server: the type of acme server used (boulder-v2 or pebble) @@ -63,12 +63,14 @@ class ACMEServer: self._processes: List[subprocess.Popen] = [] self._stdout = sys.stdout if stdout else open(os.devnull, 'w') # pylint: disable=consider-using-with self._dns_server = dns_server - self._http_01_port = http_01_port self._preterminate_cmds_args: List[Tuple[Tuple[Any, ...], Dict[str, Any]]] = [] - if http_01_port != DEFAULT_HTTP_01_PORT: - if self._acme_type != 'pebble' or self._proxy: - raise ValueError('setting http_01_port is not currently supported ' - 'with boulder or the HTTP proxy') + self._http_01_port = BOULDER_HTTP_01_PORT if self._acme_type == 'boulder' \ + else DEFAULT_HTTP_01_PORT + if http_01_port: + if (self._acme_type == 'pebble' and self._proxy) or self._acme_type == 'boulder': + raise ValueError('Setting http_01_port is not currently supported when ' + 'using Boulder or the HTTP proxy') + self._http_01_port = http_01_port def start(self) -> None: """Start the test stack""" @@ -236,11 +238,11 @@ class ACMEServer: def _prepare_http_proxy(self) -> None: """Configure and launch an HTTP proxy""" - print('=> Configuring the HTTP proxy...') + print(f'=> Configuring the HTTP proxy on port {self._http_01_port}...') http_port_map = cast(Dict[str, int], self.acme_xdist['http_port']) mapping = {r'.+\.{0}\.wtf'.format(node): 'http://127.0.0.1:{0}'.format(port) for node, port in http_port_map.items()} - command = [sys.executable, proxy.__file__, str(DEFAULT_HTTP_01_PORT), json.dumps(mapping)] + command = [sys.executable, proxy.__file__, str(self._http_01_port), json.dumps(mapping)] self._launch_process(command) print('=> Finished configuring the HTTP proxy.') diff --git a/certbot-ci/certbot_integration_tests/utils/constants.py b/certbot-ci/certbot_integration_tests/utils/constants.py index ce0cd91d5..5aabe379a 100644 --- a/certbot-ci/certbot_integration_tests/utils/constants.py +++ b/certbot-ci/certbot_integration_tests/utils/constants.py @@ -1,5 +1,6 @@ """Some useful constants to use throughout certbot-ci integration tests""" DEFAULT_HTTP_01_PORT = 5002 +BOULDER_HTTP_01_PORT = 80 TLS_ALPN_01_PORT = 5001 CHALLTESTSRV_PORT = 8055 BOULDER_V2_CHALLTESTSRV_URL = f'http://10.77.77.77:{CHALLTESTSRV_PORT}' From 8226d30af0f1576d4bca9b411dd5e7b7dc03e773 Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Fri, 27 Jan 2023 13:16:15 -0800 Subject: [PATCH 12/57] Bump up the number of operations to 30 (#9554) This is the default value, which is sensible since an "operation" basically corresponds to a GH API call, and 1 won't really let us do anything. --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 010259922..fe9b55ec9 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -39,4 +39,4 @@ jobs: take a look. # Limit the number of actions per hour, from 1-30. Default is 30 - operations-per-run: 1 + operations-per-run: 30 From 00f8d828087eefb4af7ffefee7a8c86f89f637a2 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 31 Jan 2023 12:05:01 -0800 Subject: [PATCH 13/57] double progressive percentage (#9557) --- tools/finish_release.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/finish_release.py b/tools/finish_release.py index 0a8400ea9..88db47105 100755 --- a/tools/finish_release.py +++ b/tools/finish_release.py @@ -49,7 +49,7 @@ ALL_SNAPS = ['certbot'] + PLUGIN_SNAPS # for sanity checking. SNAP_ARCH_COUNT = 3 # The percentage of users the 2.0 Certbot snap should be deployed to. -PROGRESSIVE_RELEASE_PERCENTAGE = 5 +PROGRESSIVE_RELEASE_PERCENTAGE = 10 def parse_args(args): From 1b1b27df285fc6c76d2c9639f50d2228a64aa2c5 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 31 Jan 2023 22:08:43 -0800 Subject: [PATCH 14/57] Change coverage upload condition (#9552) * change coverage upload condition * fix typo * set uploadCoverage * add comment * change coverage upload condition * verbose version --- .azure-pipelines/main.yml | 8 ++++++++ .azure-pipelines/templates/jobs/standard-tests-jobs.yml | 5 ----- .azure-pipelines/templates/steps/tox-steps.yml | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.azure-pipelines/main.yml b/.azure-pipelines/main.yml index d3c3a152e..c82647bd8 100644 --- a/.azure-pipelines/main.yml +++ b/.azure-pipelines/main.yml @@ -6,5 +6,13 @@ pr: - master - '*.x' +variables: + # We set this here to avoid coverage data being uploaded from things like our + # nightly pipeline. This is done because codecov (helpfully) keeps track of + # the number of coverage uploads for a commit and displays a warning when + # comparing two commits with an unequal number of uploads. Only uploading + # coverage here should keep the number of uploads it sees consistent. + uploadCoverage: true + jobs: - template: templates/jobs/standard-tests-jobs.yml diff --git a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml index 5d0044d19..1e6d7a352 100644 --- a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml +++ b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml @@ -11,7 +11,6 @@ jobs: macos-cover: IMAGE_NAME: macOS-12 TOXENV: cover - UPLOAD_COVERAGE: 1 windows-py37: IMAGE_NAME: windows-2019 PYTHON_VERSION: 3.7 @@ -20,12 +19,10 @@ jobs: IMAGE_NAME: windows-2019 PYTHON_VERSION: 3.9 TOXENV: cover-win - UPLOAD_COVERAGE: 1 windows-integration-certbot: IMAGE_NAME: windows-2019 PYTHON_VERSION: 3.9 TOXENV: integration-certbot - UPLOAD_COVERAGE: 1 linux-oldest-tests-1: IMAGE_NAME: ubuntu-22.04 PYTHON_VERSION: 3.7 @@ -41,7 +38,6 @@ jobs: linux-cover: IMAGE_NAME: ubuntu-22.04 TOXENV: cover - UPLOAD_COVERAGE: 1 linux-lint: IMAGE_NAME: ubuntu-22.04 TOXENV: lint-posix @@ -53,7 +49,6 @@ jobs: PYTHON_VERSION: 3.8 TOXENV: integration ACME_SERVER: pebble - UPLOAD_COVERAGE: 1 apache-compat: IMAGE_NAME: ubuntu-22.04 TOXENV: apache_compat diff --git a/.azure-pipelines/templates/steps/tox-steps.yml b/.azure-pipelines/templates/steps/tox-steps.yml index ae8a2c56b..5557bac68 100644 --- a/.azure-pipelines/templates/steps/tox-steps.yml +++ b/.azure-pipelines/templates/steps/tox-steps.yml @@ -79,5 +79,5 @@ steps: chmod +x codecov coverage xml ./codecov || echo "Uploading coverage data failed" - condition: ne(variables['UPLOAD_COVERAGE'], '') + condition: and(eq(variables['uploadCoverage'], true), or(startsWith(variables['TOXENV'], 'cover'), startsWith(variables['TOXENV'], 'integration'))) displayName: Upload coverage data From e75dc1dfd005434f54ee3bbf44fdbb1aebec1c60 Mon Sep 17 00:00:00 2001 From: alexzorin Date: Thu, 2 Feb 2023 05:48:13 +1100 Subject: [PATCH 15/57] show_account: display account thumbprint (#9540) In #9127, where @osirisinferi added the `show_account` verb, I made a call not to include the thumbprint in the output of `certbot show_account`. In hindsight, and after a community member asked for this feature, I think it's better to include it. It is useful on occasion and `show_account` is fairly specialized anyway. It's only really good for getting your account URL for rate limit increases, checking your contacts, and (now) and doing *magic* with the thumbprint for stateless/distributed HTTP-01 responders. Without this feature, a clever user might figure out their thumbprint by doing a `certonly --manual --preferred-challenges http` request, but most users would probably be lost. * show_account: display account thumbprint * use local key for display --- certbot/CHANGELOG.md | 2 +- certbot/certbot/_internal/main.py | 4 ++++ certbot/tests/main_test.py | 11 +++++++---- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index b2762eb11..225bb82e1 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -6,7 +6,7 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). ### Added -* +* `certbot show_account` now displays the [ACME Account Thumbprint](https://datatracker.ietf.org/doc/html/rfc8555#section-8.1). ### Changed diff --git a/certbot/certbot/_internal/main.py b/certbot/certbot/_internal/main.py index 316503c5d..01ee2021d 100644 --- a/certbot/certbot/_internal/main.py +++ b/certbot/certbot/_internal/main.py @@ -17,6 +17,7 @@ from typing import Union import configobj import josepy as jose +from josepy import b64 from acme import client as acme_client from acme import errors as acme_errors @@ -992,6 +993,9 @@ def show_account(config: configuration.NamespaceConfig, output = [f"Account details for server {config.server}:", f" Account URL: {regr.uri}"] + thumbprint = b64.b64encode(acc.key.thumbprint()).decode() + output.append(f" Account Thumbprint: {thumbprint}") + emails = [] for contact in regr.body.contact: diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index e857f6c33..58c4fdeed 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -2238,6 +2238,7 @@ class ShowAccountTest(test_util.ConfigTestCase): mock_storage.find_all.return_value = [mock_account] self.mocks['account'].AccountFileStorage.return_value = mock_storage mock_account.regr.body = mock_regr.body + mock_account.key.thumbprint.return_value = b'foobarbaz' self.mocks['determine_account'].return_value = (mock_account, mock.MagicMock()) def _test_show_account(self, contact): @@ -2246,7 +2247,6 @@ class ShowAccountTest(test_util.ConfigTestCase): mock_regr = mock.MagicMock() mock_regr.body.contact = contact mock_regr.uri = 'https://www.letsencrypt-demo.org/acme/reg/1' - mock_regr.body.key.thumbprint.return_value = b'foobarbaz' mock_client.acme.query_registration.return_value = mock_regr self.mocks['client'].Client.return_value = mock_client @@ -2283,7 +2283,8 @@ class ShowAccountTest(test_util.ConfigTestCase): self.mocks['notify'].assert_has_calls([ mock.call('Account details for server https://acme-v02.api.letsencr' 'ypt.org/directory:\n Account URL: https://www.letsencry' - 'pt-demo.org/acme/reg/1\n Email contact: none')]) + 'pt-demo.org/acme/reg/1\n Account Thumbprint: Zm9vYmFyYmF6\n' + ' Email contact: none')]) def test_single_email(self): contact = ('mailto:foo@example.com',) @@ -2293,7 +2294,8 @@ class ShowAccountTest(test_util.ConfigTestCase): self.mocks['notify'].assert_has_calls([ mock.call('Account details for server https://acme-v02.api.letsencr' 'ypt.org/directory:\n Account URL: https://www.letsencry' - 'pt-demo.org/acme/reg/1\n Email contact: foo@example.com')]) + 'pt-demo.org/acme/reg/1\n Account Thumbprint: Zm9vYmFyYmF6' + '\n Email contact: foo@example.com')]) def test_double_email(self): contact = ('mailto:foo@example.com', 'mailto:bar@example.com') @@ -2303,7 +2305,8 @@ class ShowAccountTest(test_util.ConfigTestCase): self.mocks['notify'].assert_has_calls([ mock.call('Account details for server https://acme-v02.api.letsencr' 'ypt.org/directory:\n Account URL: https://www.letsencry' - 'pt-demo.org/acme/reg/1\n Email contacts: foo@example.com, bar@example.com')]) + 'pt-demo.org/acme/reg/1\n Account Thumbprint: Zm9vYmFyYmF6\n' + ' Email contacts: foo@example.com, bar@example.com')]) if __name__ == '__main__': From cea717db3e5f56f696a08b3dccc488a51bb7278a Mon Sep 17 00:00:00 2001 From: alexzorin Date: Thu, 2 Feb 2023 05:49:37 +1100 Subject: [PATCH 16/57] docs: update -d flag copy to be CA-agnostic (#9542) Some confusion ensued in [this community thread](https://community.letsencrypt.org/t/connection-between-ios-9-support-and-subject-common-name-or-x509v3-subject-alternative-name-critical/191619) about the Subject CN, which Certbot omits from the CSR, Let's Encrypt includes in the issued certificate, but some other CAs do not. It's probably for the best that we do not entomb Let's Encrypt's current issuance practices in Certbot's documentation. --- certbot/certbot/_internal/cli/__init__.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/certbot/certbot/_internal/cli/__init__.py b/certbot/certbot/_internal/cli/__init__.py index d3f4a2cbe..9013b8249 100644 --- a/certbot/certbot/_internal/cli/__init__.py +++ b/certbot/certbot/_internal/cli/__init__.py @@ -115,17 +115,12 @@ def prepare_and_parse_args(plugins: plugins_disco.PluginsRegistry, args: List[st "-d", "--domains", "--domain", dest="domains", metavar="DOMAIN", action=_DomainsAction, default=flag_default("domains"), - help="Domain names to apply. For multiple domains you can use " - "multiple -d flags or enter a comma separated list of domains " - "as a parameter. The first domain provided will be the " - "subject CN of the certificate, and all domains will be " - "Subject Alternative Names on the certificate. " - "The first domain will also be used in " - "some software user interfaces and as the file paths for the " - "certificate and related material unless otherwise " - "specified or you already have a certificate with the same " - "name. In the case of a name collision it will append a number " - "like 0001 to the file path name. (default: Ask)") + help="Domain names to include. For multiple domains you can use multiple -d flags " + "or enter a comma separated list of domains as a parameter. All domains will " + "be included as Subject Alternative Names on the certificate. The first domain " + "will be used as the certificate name, unless otherwise specified or if you " + "already have a certificate with the same name. In the case of a name conflict, " + "a number like -0001 will be appended to the certificate name. (default: Ask)") helpful.add( [None, "run", "certonly", "register"], "--eab-kid", dest="eab_kid", From 71a14f5193722b2f6b01d3a128cedb2575e06fd1 Mon Sep 17 00:00:00 2001 From: Daniel McMahon <50181878+igloodan@users.noreply.github.com> Date: Wed, 1 Feb 2023 20:59:35 +0000 Subject: [PATCH 17/57] Fix docs google permissions (#9556) * include project level IAM requirements * add name to authors.md * Update certbot-dns-google/certbot_dns_google/__init__.py Co-authored-by: alexzorin * Update certbot-dns-google/certbot_dns_google/__init__.py Co-authored-by: alexzorin * Update certbot-dns-google/certbot_dns_google/__init__.py Co-authored-by: alexzorin --------- Co-authored-by: Daniel McMahon Co-authored-by: alexzorin --- AUTHORS.md | 1 + certbot-dns-google/certbot_dns_google/__init__.py | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/AUTHORS.md b/AUTHORS.md index 4b8dd9e73..410e72030 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -68,6 +68,7 @@ Authors * [Daniel Convissor](https://github.com/convissor) * [Daniel "Drex" Drexler](https://github.com/aeturnum) * [Daniel Huang](https://github.com/dhuang) +* [Daniel McMahon] (https://github.com/igloodan) * [Dave Guarino](https://github.com/daguar) * [David cz](https://github.com/dave-cz) * [David Dworken](https://github.com/ddworken) diff --git a/certbot-dns-google/certbot_dns_google/__init__.py b/certbot-dns-google/certbot_dns_google/__init__.py index 2cac34652..19f81c0c6 100644 --- a/certbot-dns-google/certbot_dns_google/__init__.py +++ b/certbot-dns-google/certbot_dns_google/__init__.py @@ -38,6 +38,19 @@ for an account with the following permissions: * ``dns.resourceRecordSets.list`` * ``dns.resourceRecordSets.update`` +(The closest role is `dns.admin `_). + +If the above permissions are assigned at the `resource level `_, the same user must +have, at the PROJECT level, the following permissions: + +* ``dns.managedZones.get`` +* ``dns.managedZones.list`` + +(The closest role is `dns.reader `_). + Google provides instructions for `creating a service account `_ and `information about the required permissions Date: Sat, 4 Feb 2023 06:35:15 +1100 Subject: [PATCH 18/57] docs: generate a man page with a structure (#9561) If you looked at [the Debian man page for Certbot](https://manpages.debian.org/bullseye/certbot/certbot.1.en.html) or [the FreeBSD one](https://man.freebsd.org/cgi/man.cgi?query=certbot&sektion=1&apropos=0&manpath=FreeBSD+13.1-RELEASE+and+Ports), you will notice that the entire document is in the "NAME" section. It looks weird in particular on the [FreeBSD man page listing](https://man.freebsd.org/cgi/man.cgi?query=certbot&apropos=1&sektion=0&manpath=FreeBSD+13.1-RELEASE+and+Ports&arch=default&format=html). This PR adds some structure to the man page by adding a new "Synopsis" section (lifted from the Certbot snap's synopsis) and shoving the `certbot --help all` output into a new "Options" section. I think this should be sustainable for us, without having to worry about the man page in particular. Fixes #9560. --- certbot/docs/conf.py | 2 +- certbot/docs/man/certbot.rst | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/certbot/docs/conf.py b/certbot/docs/conf.py index de9e287fc..5102e7a1e 100644 --- a/certbot/docs/conf.py +++ b/certbot/docs/conf.py @@ -286,7 +286,7 @@ latex_documents = [ man_pages = [ ('index', 'certbot', u'Certbot Documentation', [project], 7), - ('man/certbot', 'certbot', u'certbot script documentation', + ('man/certbot', 'certbot', u"Automatically configure HTTPS using Let's Encrypt", [project], 1), ] diff --git a/certbot/docs/man/certbot.rst b/certbot/docs/man/certbot.rst index 2f25504b0..cc690d2da 100644 --- a/certbot/docs/man/certbot.rst +++ b/certbot/docs/man/certbot.rst @@ -1,3 +1,23 @@ :orphan: -.. literalinclude:: ../cli-help.txt +======= +certbot +======= + +Synopsis +======== +The objective of Certbot, Let's Encrypt, and the ACME (Automated Certificate Management +Environment) protocol is to make it possible to set up an HTTPS server and have it automatically +obtain a browser-trusted certificate, without any human intervention. This is accomplished by +running a certificate management agent on the web server. + +This agent is used to: + +- Automatically prove to the Let's Encrypt CA that you control the website +- Obtain a browser-trusted certificate and set it up on your web server +- Keep track of when your certificate is going to expire, and renew it +- Help you revoke the certificate if that ever becomes necessary. + +Options +======= +.. literalinclude:: ../cli-help.txt \ No newline at end of file From 23090198bf132704f1c860d5b6b623a2fcb593f8 Mon Sep 17 00:00:00 2001 From: ohemorange Date: Fri, 3 Feb 2023 13:46:08 -0800 Subject: [PATCH 19/57] Configuration File Update w/o Certificate Issuance (#9355) * Add command to update config files without issuing/renewing cert * toss up a vague untested skeleton * remove duplicated code * set certname in config * consistent name, no zope * import copy * reconsitute is in renewal * import renewal * import cli * fix lint errors * call choose_configurator_plugins for its side effect of writing to config * Set certonly in choose config plugins as we do for renew * rewrite by piggybacking on existing side effects of a dry run instead * do not allow domains to be set while reconfiguring * remove unused cert_manager.reconfigure * remove unused imports * Add comments and messages * add cli information * start adding tests * remove test code * get certname before setting up plugins * get plugin from lineage if not set on cli * import copy * always reconstitute * only load cert once * add error message * improve comment * mock everything out for tests * test functionality is working! * add tests for adding and modifying hooks * test that we don't modify the config if the dry run fails * improve documentation * add webroot to reconfigure common options * lint and clean up intermediate artifacts * mock validate_hooks for windows * print success message with updated parameters * Improve success message * add message for no changes have been made * improve changed message to show before as well * syntax * Add changes will apply at the next renewal message * lint * lint really likes dict.items() for some reason * run the deploy hook * turn off dry run to test deploy hook * patch list_hooks call for tests * factor out reporting results code * Remove reporting of which values were changed * add flag to run deploy hook despite doing a dry run, and recommend setting that to yes when running reconfigure and modifying the deploy hook * missing () around multi-line string * test if the two dicts are equal instead of finding the actual changes, thus avoiding having to deal with webroot_map being a list * refer to --deploy-hook instead of deploy hook * use renewal configuration instead of configuration information * mention that the deploy hook will use the active cert not the test one * disable lint and remove new from language asking about running a deploy hook * pluralize run deploy hook(s) * Add test for reporting results when there is a webroot map * update changelog * Update error message about modifying domains on the certificate * update changelog * Add basic integration tests * Just set -a rather than redoing the whole testing infrastructure * used webroot in integration test since it's already installed * file contents are accessed twice now --------- Co-authored-by: Alex Zorin --- .../certbot_tests/test_main.py | 19 ++ certbot/CHANGELOG.md | 3 +- certbot/certbot/_internal/cli/__init__.py | 21 ++- .../certbot/_internal/cli/cli_constants.py | 1 + certbot/certbot/_internal/cli/group_adder.py | 2 +- certbot/certbot/_internal/cli/helpful.py | 1 + .../certbot/_internal/cli/plugins_parsing.py | 8 +- certbot/certbot/_internal/cli/verb_help.py | 5 + certbot/certbot/_internal/constants.py | 1 + certbot/certbot/_internal/hooks.py | 12 +- certbot/certbot/_internal/main.py | 122 +++++++++++++ certbot/certbot/_internal/renewal.py | 4 +- certbot/certbot/_internal/storage.py | 15 ++ certbot/tests/main_test.py | 164 +++++++++++++++++- certbot/tests/renewal_test.py | 2 +- 15 files changed, 360 insertions(+), 20 deletions(-) diff --git a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py index 356eaa774..170104544 100644 --- a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py +++ b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py @@ -808,6 +808,25 @@ def test_revoke_multiple_lineages(context: IntegrationTestsContext) -> None: assert 'Not deleting revoked certificates due to overlapping archive dirs' in f.read() +def test_reconfigure(context: IntegrationTestsContext) -> None: + """Test the reconfigure verb""" + certname = context.get_domain() + context.certbot(['-d', certname]) + conf_path = join(context.config_dir, 'renewal', '{}.conf'.format(certname)) + + with misc.create_http_server(context.http_01_port) as webroot: + context.certbot(['reconfigure', '--cert-name', certname, + '-a', 'webroot', '--webroot-path', webroot]) + with open(conf_path, 'r') as f: + file_contents = f.read() + # Check changed value + assert 'authenticator = webroot' in file_contents, \ + 'Expected authenticator to be changed to webroot in renewal config' + # Check added value + assert f'webroot_path = {webroot}' in file_contents, \ + 'Expected new webroot path to be added to renewal config' + + def test_wildcard_certificates(context: IntegrationTestsContext) -> None: """Test wildcard certificate issuance.""" certname = context.get_domain('wild') diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index 225bb82e1..ab1bcc963 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -6,6 +6,7 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). ### Added +* Allow a user to modify the configuration of a certificate without renewing it using the new `reconfigure` subcommand. See `certbot help reconfigure` for details. * `certbot show_account` now displays the [ACME Account Thumbprint](https://datatracker.ietf.org/doc/html/rfc8555#section-8.1). ### Changed @@ -201,7 +202,7 @@ More details about these changes can be found on our GitHub repo. ### Added -* Updated Windows installer to be signed and trusted in Windows +* Updated Windows installer to be signed and trusted in Windows ### Changed diff --git a/certbot/certbot/_internal/cli/__init__.py b/certbot/certbot/_internal/cli/__init__.py index 9013b8249..bb4f0eaa1 100644 --- a/certbot/certbot/_internal/cli/__init__.py +++ b/certbot/certbot/_internal/cli/__init__.py @@ -135,7 +135,7 @@ def prepare_and_parse_args(plugins: plugins_disco.PluginsRegistry, args: List[st ) helpful.add( [None, "run", "certonly", "manage", "delete", "certificates", - "renew", "enhance"], "--cert-name", dest="certname", + "renew", "enhance", "reconfigure"], "--cert-name", dest="certname", metavar="CERTNAME", default=flag_default("certname"), help="Certificate name to apply. This name is used by Certbot for housekeeping " "and in file paths; it doesn't affect the content of the certificate itself. " @@ -157,6 +157,17 @@ def prepare_and_parse_args(plugins: plugins_disco.PluginsRegistry, args: List[st " roll back those changes. It also calls --pre-hook and --post-hook commands" " if they are defined because they may be necessary to accurately simulate" " renewal. --deploy-hook commands are not called.") + helpful.add( + ["testing", "renew", "certonly", "reconfigure"], + "--run-deploy-hooks", action="store_true", dest="run_deploy_hooks", + default=flag_default("run_deploy_hooks"), + help="When performing a test run using `--dry-run` or `reconfigure`, run any applicable" + " deploy hooks. This includes hooks set on the command line, saved in the" + " certificate's renewal configuration file, or present in the renewal-hooks directory." + " To exclude direcory hooks, use --no-directory-hooks. The hook(s) will only" + " be run if the dry run succeeds, and will use the current active certificate, not" + " the temporary test certificate acquired during the dry run. This flag is recommended" + " when modifying the deploy hook using `reconfigure`.") helpful.add( ["register", "automation"], "--register-unsafely-without-email", action="store_true", default=flag_default("register_unsafely_without_email"), @@ -374,7 +385,7 @@ def prepare_and_parse_args(plugins: plugins_disco.PluginsRegistry, args: List[st default=flag_default("issuance_timeout"), help=config_help("issuance_timeout")) helpful.add( - "renew", "--pre-hook", + ["renew", "reconfigure"], "--pre-hook", help="Command to be run in a shell before obtaining any certificates." " Intended primarily for renewal, where it can be used to temporarily" " shut down a webserver that might conflict with the standalone" @@ -382,21 +393,21 @@ def prepare_and_parse_args(plugins: plugins_disco.PluginsRegistry, args: List[st " obtained/renewed. When renewing several certificates that have" " identical pre-hooks, only the first will be executed.") helpful.add( - "renew", "--post-hook", + ["renew", "reconfigure"], "--post-hook", help="Command to be run in a shell after attempting to obtain/renew" " certificates. Can be used to deploy renewed certificates, or to" " restart any servers that were stopped by --pre-hook. This is only" " run if an attempt was made to obtain/renew a certificate. If" " multiple renewed certificates have identical post-hooks, only" " one will be run.") - helpful.add("renew", "--renew-hook", + helpful.add(["renew", "reconfigure"], "--renew-hook", action=_RenewHookAction, help=argparse.SUPPRESS) helpful.add( "renew", "--no-random-sleep-on-renew", action="store_false", default=flag_default("random_sleep_on_renew"), dest="random_sleep_on_renew", help=argparse.SUPPRESS) helpful.add( - "renew", "--deploy-hook", action=_DeployHookAction, + ["renew", "reconfigure"], "--deploy-hook", action=_DeployHookAction, help='Command to be run in a shell once for each successfully' ' issued certificate. For this command, the shell variable' ' $RENEWED_LINEAGE will point to the config live subdirectory' diff --git a/certbot/certbot/_internal/cli/cli_constants.py b/certbot/certbot/_internal/cli/cli_constants.py index 64b94a8ab..cbf7b6a03 100644 --- a/certbot/certbot/_internal/cli/cli_constants.py +++ b/certbot/certbot/_internal/cli/cli_constants.py @@ -38,6 +38,7 @@ manage certificates: certificates Display information about certificates you have from Certbot revoke Revoke a certificate (supply --cert-name or --cert-path) delete Delete a certificate (supply --cert-name) + reconfigure Update a certificate's configuration (supply --cert-name) manage your account: register Create an ACME account diff --git a/certbot/certbot/_internal/cli/group_adder.py b/certbot/certbot/_internal/cli/group_adder.py index 96d58824b..1bbbe0215 100644 --- a/certbot/certbot/_internal/cli/group_adder.py +++ b/certbot/certbot/_internal/cli/group_adder.py @@ -16,7 +16,7 @@ def _add_all_groups(helpful: "helpful.HelpfulArgumentParser") -> None: helpful.add_group("paths", description="Flags for changing execution paths & servers") helpful.add_group("manage", description="Various subcommands and flags are available for managing your certificates:", - verbs=["certificates", "delete", "renew", "revoke", "update_symlinks"]) + verbs=["certificates", "delete", "renew", "revoke", "update_symlinks", "reconfigure"]) # VERBS for verb, docs in VERB_HELP: diff --git a/certbot/certbot/_internal/cli/helpful.py b/certbot/certbot/_internal/cli/helpful.py index cf3615fd4..0dd72e53a 100644 --- a/certbot/certbot/_internal/cli/helpful.py +++ b/certbot/certbot/_internal/cli/helpful.py @@ -66,6 +66,7 @@ class HelpfulArgumentParser: "certificates": main.certificates, "delete": main.delete, "enhance": main.enhance, + "reconfigure": main.reconfigure, } # Get notification function for printing diff --git a/certbot/certbot/_internal/cli/plugins_parsing.py b/certbot/certbot/_internal/cli/plugins_parsing.py index d19825738..d01d9903b 100644 --- a/certbot/certbot/_internal/cli/plugins_parsing.py +++ b/certbot/certbot/_internal/cli/plugins_parsing.py @@ -22,9 +22,9 @@ def _plugins_parsing(helpful: "helpful.HelpfulArgumentParser", help="Name of the plugin that is both an authenticator and an installer." " Should not be used together with --authenticator or --installer. " "(default: Ask)") - helpful.add("plugins", "-a", "--authenticator", default=flag_default("authenticator"), - help="Authenticator plugin name.") - helpful.add("plugins", "-i", "--installer", default=flag_default("installer"), + helpful.add(["plugins", "reconfigure"], "-a", "--authenticator", + default=flag_default("authenticator"), help="Authenticator plugin name.") + helpful.add(["plugins", "reconfigure"], "-i", "--installer", default=flag_default("installer"), help="Installer plugin name (also used to find domains).") helpful.add(["plugins", "certonly", "run", "install"], "--apache", action="store_true", default=flag_default("apache"), @@ -38,7 +38,7 @@ def _plugins_parsing(helpful: "helpful.HelpfulArgumentParser", helpful.add(["plugins", "certonly"], "--manual", action="store_true", default=flag_default("manual"), help="Provide laborious manual instructions for obtaining a certificate") - helpful.add(["plugins", "certonly"], "--webroot", action="store_true", + helpful.add(["plugins", "certonly", "reconfigure"], "--webroot", action="store_true", default=flag_default("webroot"), help="Obtain certificates by placing files in a webroot directory.") helpful.add(["plugins", "certonly"], "--dns-cloudflare", action="store_true", diff --git a/certbot/certbot/_internal/cli/verb_help.py b/certbot/certbot/_internal/cli/verb_help.py index b15be4631..9f805035e 100644 --- a/certbot/certbot/_internal/cli/verb_help.py +++ b/certbot/certbot/_internal/cli/verb_help.py @@ -102,6 +102,11 @@ VERB_HELP = [ "opts": 'Options useful for the "show_account" subcommand:', "usage": "\n\n certbot show_account [options]\n\n" }), + ("reconfigure", { + "short": "Update renewal configuration for a certificate specified by --cert-name", + "opts": 'Common options that may be updated with the "reconfigure" subcommand:', + "usage": "\n\n certbot reconfigure --cert-name CERTNAME [options]\n\n" + }), ] diff --git a/certbot/certbot/_internal/constants.py b/certbot/certbot/_internal/constants.py index bd999bf6a..35ee5d54e 100644 --- a/certbot/certbot/_internal/constants.py +++ b/certbot/certbot/_internal/constants.py @@ -80,6 +80,7 @@ CLI_DEFAULTS: Dict[str, Any] = dict( # noqa eab_hmac_key=None, eab_kid=None, issuance_timeout=90, + run_deploy_hooks=False, # Subparsers num=None, diff --git a/certbot/certbot/_internal/hooks.py b/certbot/certbot/_internal/hooks.py index 76cda466a..0517e625a 100644 --- a/certbot/certbot/_internal/hooks.py +++ b/certbot/certbot/_internal/hooks.py @@ -166,7 +166,7 @@ def deploy_hook(config: configuration.NamespaceConfig, domains: List[str], """ if config.deploy_hook: _run_deploy_hook(config.deploy_hook, domains, - lineage_path, config.dry_run) + lineage_path, config.dry_run, config.run_deploy_hooks) def renew_hook(config: configuration.NamespaceConfig, domains: List[str], @@ -190,7 +190,7 @@ def renew_hook(config: configuration.NamespaceConfig, domains: List[str], executed_dir_hooks = set() if config.directory_hooks: for hook in list_hooks(config.renewal_deploy_hooks_dir): - _run_deploy_hook(hook, domains, lineage_path, config.dry_run) + _run_deploy_hook(hook, domains, lineage_path, config.dry_run, config.run_deploy_hooks) executed_dir_hooks.add(hook) if config.renew_hook: @@ -199,10 +199,11 @@ def renew_hook(config: configuration.NamespaceConfig, domains: List[str], config.renew_hook) else: _run_deploy_hook(config.renew_hook, domains, - lineage_path, config.dry_run) + lineage_path, config.dry_run, config.run_deploy_hooks) -def _run_deploy_hook(command: str, domains: List[str], lineage_path: str, dry_run: bool) -> None: +def _run_deploy_hook(command: str, domains: List[str], lineage_path: str, dry_run: bool, + run_deploy_hooks: bool) -> None: """Run the specified deploy-hook (if not doing a dry run). If dry_run is True, command is not run and a message is logged @@ -214,9 +215,10 @@ def _run_deploy_hook(command: str, domains: List[str], lineage_path: str, dry_ru :type domains: `list` of `str` :param str lineage_path: live directory path for the new cert :param bool dry_run: True iff Certbot is doing a dry run + :param bool run_deploy_hooks: True if deploy hooks should run despite Certbot doing a dry run """ - if dry_run: + if dry_run and not run_deploy_hooks: logger.info("Dry run: skipping deploy hook command: %s", command) return diff --git a/certbot/certbot/_internal/main.py b/certbot/certbot/_internal/main.py index 01ee2021d..78e6347f9 100644 --- a/certbot/certbot/_internal/main.py +++ b/certbot/certbot/_internal/main.py @@ -1,6 +1,7 @@ """Certbot main entry point.""" # pylint: disable=too-many-lines +import copy from contextlib import contextmanager import functools import logging.handlers @@ -1658,6 +1659,127 @@ def make_or_verify_needed_dirs(config: configuration.NamespaceConfig) -> None: util.make_or_verify_dir(hook_dir, strict=config.strict_permissions) +def _report_reconfigure_results(renewal_file: str, orig_renewal_conf: configobj.ConfigObj) -> None: + """Reports the outcome of certificate renewal reconfiguration to the user. + + :param renewal_file: Path to the cert's renewal file + :type renewal_file: str + + :param orig_renewal_conf: Loaded original renewal configuration + :type orig_renewal_conf: configobj.ConfigObj + + :returns: `None` + :rtype: None + + """ + try: + final_renewal_conf = configobj.ConfigObj( + renewal_file, encoding='utf-8', default_encoding='utf-8') + except configobj.ConfigObjError: + raise errors.CertStorageError( + f'error parsing {renewal_file}') + + orig_renewal_params = orig_renewal_conf['renewalparams'] + final_renewal_params = final_renewal_conf['renewalparams'] + + if final_renewal_params == orig_renewal_params: + success_message = '\nNo changes were made to the renewal configuration.' + else: + success_message = '\nSuccessfully updated configuration.' + \ + '\nChanges will apply when the certificate renews.' + + display_util.notify(success_message) + + +def reconfigure(config: configuration.NamespaceConfig, + plugins: plugins_disco.PluginsRegistry) -> None: + """Allow the user to set new configuration options for an existing certificate without + forcing renewal. This can be used for things like authenticator, installer, and hooks, + but not for the domains on the cert, since those are only saved in the cert. + + :param config: Configuration object + :type config: configuration.NamespaceConfig + + :param plugins: List of plugins + :type plugins: plugins_disco.PluginsRegistry + + :raises errors.Error: if the dry run fails + :raises errors.ConfigurationError: if certificate could not be loaded + + """ + + if config.domains: + raise errors.ConfigurationError("You have specified domains, but this function cannot " + "be used to modify the domains in a certificate. If you would like to do so, follow " + "the instructions at https://certbot.org/change-cert-domain. Otherwise, remove the " + "domains from the command to continue reconfiguring. You can specify which certificate " + "you want on the command line with flag --cert-name instead.") + # While we could technically allow domains to be used to specify the certificate in addition to + # --cert-name, there's enough complexity with matching certs to domains that it's not worth it, + # to say nothing of the difficulty in explaining what exactly this subcommand can modify + + + # To make sure that the requested changes work, do a dry run. While setting up the dry run, + # we will set all the needed fields in config, which will then be saved upon success. + config.dry_run = True + + if not config.certname: + certname_question = "Which certificate would you like to reconfigure?" + config.certname = cert_manager.get_certnames( + config, "reconfigure", allow_multiple=False, + custom_prompt=certname_question)[0] + + certname = config.certname + + try: + renewal_file = storage.renewal_file_for_certname(config, certname) + except errors.CertStorageError: + raise errors.ConfigurationError(f"An existing certificate with name {certname} could not " + "be found. Run `certbot certificates` to list available certificates.") + + # figure this out before we modify config + if config.deploy_hook and not config.run_deploy_hooks: + msg = ("You are attempting to set a --deploy-hook. Would you like Certbot to run deploy " + "hooks when it performs a dry run with the new settings? This will run all " + "relevant deploy hooks, including directory hooks, unless --no-directory-hooks " + "is set. This will use the current active certificate, and not the temporary test " + "certificate acquired during the dry run.") + config.run_deploy_hooks = display_util.yesno(msg,"Run deploy hooks", + "Do not run deploy hooks", default=False) + + # cache previous version for later comparison + try: + orig_renewal_conf = configobj.ConfigObj( + renewal_file, encoding='utf-8', default_encoding='utf-8') + except configobj.ConfigObjError: + raise errors.CertStorageError( + f"error parsing {renewal_file}") + + lineage_config = copy.deepcopy(config) + try: + renewal_candidate = renewal.reconstitute(lineage_config, renewal_file) + except Exception as e: # pylint: disable=broad-except + raise errors.ConfigurationError(f"Renewal configuration file {renewal_file} " + f"(cert: {certname}) produced an unexpected error: {e}.") + if not renewal_candidate: + raise errors.ConfigurationError("Could not load certificate. See logs for errors.") + + # this is where lineage_config gets fully filled out (e.g. --apache will set auth and installer) + installer, auth = plug_sel.choose_configurator_plugins(lineage_config, plugins, "certonly") + le_client = _init_le_client(lineage_config, auth, installer) + + # renews cert as dry run to test that the new values are ok + # at this point, renewal_candidate.configuration has the old values, but will use + # the values from lineage_config when doing the dry run + _get_and_save_cert(le_client, lineage_config, certname=certname, + lineage=renewal_candidate) + + # this function will update lineage.configuration with the new values, and save it to disk + renewal_candidate.save_new_config_values(lineage_config) + + _report_reconfigure_results(renewal_file, orig_renewal_conf) + + @contextmanager def make_displayer(config: configuration.NamespaceConfig ) -> Generator[Union[display_obj.NoninteractiveDisplay, diff --git a/certbot/certbot/_internal/renewal.py b/certbot/certbot/_internal/renewal.py index ea5e0435f..39f704f2f 100644 --- a/certbot/certbot/_internal/renewal.py +++ b/certbot/certbot/_internal/renewal.py @@ -53,7 +53,7 @@ CONFIG_ITEMS = set(itertools.chain( BOOL_CONFIG_ITEMS, INT_CONFIG_ITEMS, STR_CONFIG_ITEMS, ('pref_challs',))) -def _reconstitute(config: configuration.NamespaceConfig, +def reconstitute(config: configuration.NamespaceConfig, full_path: str) -> Optional[storage.RenewableCert]: """Try to instantiate a RenewableCert, updating config with relevant items. @@ -491,7 +491,7 @@ def handle_renewal_request(config: configuration.NamespaceConfig) -> None: # Note that this modifies config (to add back the configuration # elements from within the renewal configuration file). try: - renewal_candidate = _reconstitute(lineage_config, renewal_file) + renewal_candidate = reconstitute(lineage_config, renewal_file) except Exception as e: # pylint: disable=broad-except logger.error("Renewal configuration file %s (cert: %s) " "produced an unexpected error: %s. Skipping.", diff --git a/certbot/certbot/_internal/storage.py b/certbot/certbot/_internal/storage.py index 6c483734e..7e7c1e639 100644 --- a/certbot/certbot/_internal/storage.py +++ b/certbot/certbot/_internal/storage.py @@ -46,6 +46,8 @@ README = "README" CURRENT_VERSION = pkg_resources.parse_version(certbot.__version__) BASE_PRIVKEY_MODE = 0o600 +# pylint: disable=too-many-lines + def renewal_conf_files(config: configuration.NamespaceConfig) -> List[str]: """Build a list of all renewal configuration files. @@ -1245,6 +1247,19 @@ class RenewableCert(interfaces.RenewableCert): return target_version + def save_new_config_values(self, cli_config: configuration.NamespaceConfig) -> None: + """Save only the config information without writing the new cert. + + :param .NamespaceConfig cli_config: parsed command line + arguments + """ + self.cli_config = cli_config + symlinks = {kind: self.configuration[kind] for kind in ALL_FOUR} + # Update renewal config file + self.configfile = update_configuration( + self.lineagename, self.archive_dir, symlinks, cli_config) + self.configuration = config_with_defaults(self.configfile) + def truncate(self, num_prior_certs_to_keep: int = 5) -> None: """Delete unused historical certificate, chain and key items from the lineage. diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index 58c4fdeed..4b416272f 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -14,6 +14,7 @@ from typing import List import unittest from unittest import mock +import configobj import josepy as jose import pytz @@ -530,6 +531,167 @@ class RevokeTest(test_util.TempDirTestCase): self._call() self.assertIs(mock_delete.called, False) + +class ReconfigureTest(test_util.TempDirTestCase): + """Tests for certbot._internal.main.reconfigure""" + + def setUp(self): + super().setUp() + self.get_utility_patch = test_util.patch_display_util() + self.mock_get_utility = self.get_utility_patch.start() + self.patchers = { + 'check_symlinks': mock.patch('certbot._internal.storage.RenewableCert._check_symlinks'), + 'cert_names': mock.patch('certbot._internal.storage.RenewableCert.names'), + 'pick_installer': mock.patch('certbot._internal.plugins.selection.pick_installer'), + 'pick_auth': mock.patch('certbot._internal.plugins.selection.pick_authenticator'), + 'find_init': mock.patch('certbot._internal.plugins.disco.PluginsRegistry.find_init'), + '_get_and_save_cert': mock.patch('certbot._internal.main._get_and_save_cert'), + '_init_le_client': mock.patch('certbot._internal.main._init_le_client'), + 'list_hooks': mock.patch('certbot._internal.hooks.list_hooks'), + } + self.mocks = {k: v.start() for k, v in self.patchers.items()} + self.mocks['cert_names'].return_value = ['example.com'] + + self.config_dir = os.path.join(self.tempdir, 'config') + renewal_configs_dir = os.path.join(self.config_dir, 'renewal') + if not os.path.exists(renewal_configs_dir): + filesystem.makedirs(renewal_configs_dir) + self.renewal_file = os.path.join(renewal_configs_dir, 'example.com.conf') + original_config = """ + version = 1.32.0 + archive_dir = /etc/letsencrypt/archive/example.com + cert = /etc/letsencrypt/live/example.com/cert.pem + privkey = /etc/letsencrypt/live/example.com/privkey.pem + chain = /etc/letsencrypt/live/example.com/chain.pem + fullchain = /etc/letsencrypt/live/example.com/fullchain.pem + + # Options used in the renewal process + [renewalparams] + account = ee43634db0aa4e6804f152be39990e6a + server = https://acme-staging-v02.api.letsencrypt.org/directory + authenticator = nginx + installer = nginx + key_type = rsa + """ + with open(self.renewal_file, 'w') as f: + f.write(original_config) + with open(self.renewal_file, 'r') as f: + self.original_config = configobj.ConfigObj(f, + encoding='utf-8', default_encoding='utf-8') + + + def tearDown(self): + super().tearDown() + self.get_utility_patch.stop() + for patch in self.patchers.values(): + patch.stop() + + def _call(self, passed_args): + full_args = passed_args + ['--config-dir', self.config_dir] + cli.set_by_cli.detector = None # required to reset set_by_cli state + plugins = disco.PluginsRegistry.find_all() + config = configuration.NamespaceConfig( + cli.prepare_and_parse_args(plugins, full_args)) + + from certbot._internal.main import reconfigure + reconfigure(config, plugins) + + with open(self.renewal_file, 'r') as f: + updated_conf = configobj.ConfigObj(f, encoding='utf-8', default_encoding='utf-8') + + return updated_conf + + def test_domains_set(self): + self.assertRaises(errors.ConfigurationError, + self._call, '--cert-name cert1 -d one.cert.com'.split()) + + @mock.patch('certbot._internal.cert_manager.get_certnames') + def test_asks_for_certname(self, mock_cert_manager): + mock_cert_manager.return_value = ['example.com'] + self._call('--nginx'.split()) + self.assertEqual(mock_cert_manager.call_count, 1) + + def test_update_configurator(self): + named_mock = mock.Mock() + named_mock.name = 'apache' + + self.mocks['pick_installer'].return_value = named_mock + self.mocks['pick_auth'].return_value = named_mock + self.mocks['find_init'].return_value = named_mock + + new_config = self._call('--cert-name example.com --apache'.split()) + self.assertEqual(new_config['renewalparams']['authenticator'], 'apache') + + @mock.patch('certbot._internal.hooks.validate_hooks') + def test_update_hooks(self, unused_validate_hooks): + self.assertNotIn('pre_hook', self.original_config) + # test set + new_config = self._call('--cert-name example.com --pre-hook'.split() + ['echo pre']) + self.assertEqual(new_config['renewalparams']['pre_hook'], 'echo pre') + # test update + new_config = self._call('--cert-name example.com --pre-hook'.split() + ['echo pre2']) + self.assertEqual(new_config['renewalparams']['pre_hook'], 'echo pre2') + + # test deploy hook is set even though we did a dry run + self.assertNotIn('renew_hook', self.original_config) + new_config = self._call('--cert-name example.com --deploy-hook'.split() + ['echo deploy']) + self.assertEqual(new_config['renewalparams']['renew_hook'], 'echo deploy') + + def test_dry_run_fails(self): + # set side effect of raising error + self.mocks['_get_and_save_cert'].side_effect = errors.Error + + try: + self._call('--cert-name example.com --apache'.split()) + except errors.Error: + pass + + # check that config isn't modified + with open(self.renewal_file, 'r') as f: + new_config = configobj.ConfigObj(f, encoding='utf-8', default_encoding='utf-8') + self.assertEqual(new_config['renewalparams']['authenticator'], 'nginx') + + @mock.patch('certbot._internal.main.display_util.notify') + def test_report_results(self, mock_notify): + # make sure report results works when config has a webroot map + original_config = """ + version = 2.0.0 + archive_dir = /etc/letsencrypt/archive/example.com + cert = /etc/letsencrypt/live/example.com/cert.pem + privkey = /etc/letsencrypt/live/example.com/privkey.pem + chain = /etc/letsencrypt/live/example.com/chain.pem + fullchain = /etc/letsencrypt/live/example.com/fullchain.pem + + # Options used in the renewal process + [renewalparams] + account = ee43634db0aa4e6804f152be39990e6a + server = https://acme-staging-v02.api.letsencrypt.org/directory + authenticator = webroot + installer = nginx + key_type = ecdsa + webroot_path = /var/www/html, + [[webroot_map]] + example.com = /var/www/html + """ + with open(self.renewal_file, 'w') as f: + f.write(original_config) + with open(self.renewal_file, 'r') as f: + self.original_config = configobj.ConfigObj(f, + encoding='utf-8', default_encoding='utf-8') + + named_mock = mock.Mock() + named_mock.name = 'nginx' + + self.mocks['pick_auth'].return_value = named_mock + self.mocks['find_init'].return_value = named_mock + + new_config = self._call('--cert-name example.com --nginx'.split()) + self.assertEqual(new_config['renewalparams']['authenticator'], 'nginx') + mock_notify.assert_called_with( + '\nSuccessfully updated configuration.'+ + '\nChanges will apply when the certificate renews.') + + class DeleteIfAppropriateTest(test_util.ConfigTestCase): """Tests for certbot._internal.main._delete_if_appropriate """ @@ -1492,7 +1654,7 @@ class MainTest(test_util.ConfigTestCase): def test_renew_reconstitute_error(self): # pylint: disable=protected-access - with mock.patch('certbot._internal.main.renewal._reconstitute') as mock_reconstitute: + with mock.patch('certbot._internal.main.renewal.reconstitute') as mock_reconstitute: mock_reconstitute.side_effect = Exception self._test_renew_common(assert_oc_called=False, error_expected=True) diff --git a/certbot/tests/renewal_test.py b/certbot/tests/renewal_test.py index ce6065091..3cb4ac056 100644 --- a/certbot/tests/renewal_test.py +++ b/certbot/tests/renewal_test.py @@ -168,7 +168,7 @@ class RenewalTest(test_util.ConfigTestCase): from certbot._internal import renewal lineage_config = copy.deepcopy(self.config) - renewal_candidate = renewal._reconstitute(lineage_config, rc_path) + renewal_candidate = renewal.reconstitute(lineage_config, rc_path) # This means that manual_public_ip_logging_ok was not modified in the config based on its # value in the renewal conf file self.assertIsInstance(lineage_config.manual_public_ip_logging_ok, mock.MagicMock) From 99184daff632e71ca1fae0298f07b203d5fd7638 Mon Sep 17 00:00:00 2001 From: alexzorin Date: Thu, 9 Feb 2023 06:17:44 +1100 Subject: [PATCH 20/57] repin cryptography for openssl security update (#9565) * repin cryptography for openssl security update https://www.openssl.org/news/secadv/20230207.txt https://cryptography.io/en/latest/changelog/#v39-0-1 * fix type hints * remove outdated comments --- .../certbot_tests/assertions.py | 12 +-- .../certbot_tests/test_main.py | 8 +- .../certbot_integration_tests/utils/misc.py | 6 +- .../utils/pebble_ocsp_server.py | 8 +- .../_internal/dns_rfc2136.py | 10 +- certbot/certbot/_internal/storage.py | 3 +- certbot/certbot/crypto_util.py | 12 +-- certbot/certbot/ocsp.py | 1 + certbot/certbot/tests/util.py | 6 +- tools/requirements.txt | 96 +++++++++---------- 10 files changed, 84 insertions(+), 78 deletions(-) diff --git a/certbot-ci/certbot_integration_tests/certbot_tests/assertions.py b/certbot-ci/certbot_integration_tests/certbot_tests/assertions.py index a1e814405..7731f27d7 100644 --- a/certbot-ci/certbot_integration_tests/certbot_tests/assertions.py +++ b/certbot-ci/certbot_integration_tests/certbot_tests/assertions.py @@ -22,13 +22,13 @@ SYSTEM_SID = 'S-1-5-18' ADMINS_SID = 'S-1-5-32-544' -def assert_elliptic_key(key: str, curve: Type[EllipticCurve]) -> None: +def assert_elliptic_key(key_path: str, curve: Type[EllipticCurve]) -> None: """ Asserts that the key at the given path is an EC key using the given curve. - :param key: path to key + :param key_path: path to key :param EllipticCurve curve: name of the expected elliptic curve """ - with open(key, 'rb') as file: + with open(key_path, 'rb') as file: privkey1 = file.read() key = load_pem_private_key(data=privkey1, password=None, backend=default_backend()) @@ -37,13 +37,13 @@ def assert_elliptic_key(key: str, curve: Type[EllipticCurve]) -> None: assert isinstance(key.curve, curve), f"should have curve {curve} but was {key.curve}" -def assert_rsa_key(key: str, key_size: Optional[int] = None) -> None: +def assert_rsa_key(key_path: str, key_size: Optional[int] = None) -> None: """ Asserts that the key at the given path is an RSA key. - :param str key: path to key + :param str key_path: path to key :param int key_size: if provided, assert that the RSA key is of this size """ - with open(key, 'rb') as file: + with open(key_path, 'rb') as file: privkey1 = file.read() key = load_pem_private_key(data=privkey1, password=None, backend=default_backend()) diff --git a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py index 170104544..66aa1aa23 100644 --- a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py +++ b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py @@ -916,7 +916,7 @@ def test_preferred_chain(context: IntegrationTestsContext) -> None: except NotImplementedError: pytest.skip('This ACME server does not support alternative issuers.') - names = [i.issuer.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value \ + names = [str(i.issuer.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value) \ for i in issuers] domain = context.get_domain('preferred-chain') @@ -929,9 +929,9 @@ def test_preferred_chain(context: IntegrationTestsContext) -> None: context.certbot(args) dumped = misc.read_certificate(cert_path) - assert 'Issuer: CN={}'.format(expected) in dumped, \ - 'Expected chain issuer to be {} when preferring {}'.format(expected, requested) + assert f'Issuer: CN={expected}'in dumped, \ + f'Expected chain issuer to be {expected} when preferring {requested}' with open(conf_path, 'r') as f: - assert 'preferred_chain = {}'.format(requested) in f.read(), \ + assert f'preferred_chain = {requested}' in f.read(), \ 'Expected preferred_chain to be set in renewal config' diff --git a/certbot-ci/certbot_integration_tests/utils/misc.py b/certbot-ci/certbot_integration_tests/utils/misc.py index f21f7492a..9d6317d87 100644 --- a/certbot-ci/certbot_integration_tests/utils/misc.py +++ b/certbot-ci/certbot_integration_tests/utils/misc.py @@ -230,11 +230,7 @@ def generate_csr(domains: Iterable[str], key_path: str, csr_path: str, # Ignore a warning on some old versions of cryptography warnings.simplefilter('ignore', category=PendingDeprecationWarning) _key = ec.generate_private_key(ec.SECP384R1(), default_backend()) - # This type ignore directive is required due to an outdated version of types-cryptography. - # It can be removed once package types-pyOpenSSL depends on cryptography instead of - # types-cryptography and so types-cryptography is not installed anymore. - # See https://github.com/python/typeshed/issues/5618 - _bytes = _key.private_bytes(encoding=Encoding.PEM, # type: ignore + _bytes = _key.private_bytes(encoding=Encoding.PEM, format=PrivateFormat.TraditionalOpenSSL, encryption_algorithm=NoEncryption()) key = crypto.load_privatekey(crypto.FILETYPE_PEM, _bytes) diff --git a/certbot-ci/certbot_integration_tests/utils/pebble_ocsp_server.py b/certbot-ci/certbot_integration_tests/utils/pebble_ocsp_server.py index e9c8acd49..d0f7a2123 100755 --- a/certbot-ci/certbot_integration_tests/utils/pebble_ocsp_server.py +++ b/certbot-ci/certbot_integration_tests/utils/pebble_ocsp_server.py @@ -11,9 +11,13 @@ from cryptography import x509 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateKey +from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey from cryptography.x509 import ocsp from dateutil import parser import requests +from typing import cast +from typing import Union from certbot_integration_tests.utils.constants import MOCK_OCSP_SERVER_PORT from certbot_integration_tests.utils.constants import PEBBLE_MANAGEMENT_URL @@ -25,7 +29,9 @@ class _ProxyHandler(BaseHTTPServer.BaseHTTPRequestHandler): def do_POST(self) -> None: request = requests.get(PEBBLE_MANAGEMENT_URL + '/intermediate-keys/0', verify=False, timeout=10) - issuer_key = serialization.load_pem_private_key(request.content, None, default_backend()) + issuer_key = cast( + Union[RSAPrivateKey, EllipticCurvePrivateKey], + serialization.load_pem_private_key(request.content, None, default_backend())) request = requests.get(PEBBLE_MANAGEMENT_URL + '/intermediates/0', verify=False, timeout=10) diff --git a/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py b/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py index 2c52486e2..d48307750 100644 --- a/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py +++ b/certbot-dns-rfc2136/certbot_dns_rfc2136/_internal/dns_rfc2136.py @@ -138,7 +138,7 @@ class _RFC2136Client: except Exception as e: raise errors.PluginError('Encountered error adding TXT record: {0}' .format(e)) - rcode = response.rcode() # type: ignore[attr-defined] + rcode = response.rcode() if rcode == dns.rcode.NOERROR: logger.debug('Successfully added TXT record %s', record_name) @@ -173,7 +173,7 @@ class _RFC2136Client: except Exception as e: raise errors.PluginError('Encountered error deleting TXT record: {0}' .format(e)) - rcode = response.rcode() # type: ignore[attr-defined] + rcode = response.rcode() if rcode == dns.rcode.NOERROR: logger.debug('Successfully deleted TXT record %s', record_name) @@ -217,7 +217,7 @@ class _RFC2136Client: # Turn off Recursion Desired bit in query request.flags ^= dns.flags.RD # Use our TSIG keyring - request.use_tsig(self.keyring, algorithm=self.algorithm) # type: ignore[attr-defined] + request.use_tsig(self.keyring, algorithm=self.algorithm) try: try: @@ -225,11 +225,11 @@ class _RFC2136Client: except (OSError, dns.exception.Timeout) as e: logger.debug('TCP query failed, fallback to UDP: %s', e) response = dns.query.udp(request, self.server, self._default_timeout, self.port) - rcode = response.rcode() # type: ignore[attr-defined] + rcode = response.rcode() # Authoritative Answer bit should be set if (rcode == dns.rcode.NOERROR - and response.get_rrset(response.answer, # type: ignore[attr-defined] + and response.get_rrset(response.answer, domain, dns.rdataclass.IN, dns.rdatatype.SOA) and response.flags & dns.flags.AA): logger.debug('Received authoritative SOA response for %s', domain_name) diff --git a/certbot/certbot/_internal/storage.py b/certbot/certbot/_internal/storage.py index 7e7c1e639..cb6d2ef16 100644 --- a/certbot/certbot/_internal/storage.py +++ b/certbot/certbot/_internal/storage.py @@ -7,6 +7,7 @@ import re import shutil import stat from typing import Any +from typing import cast from typing import Dict from typing import Iterable from typing import List @@ -1133,7 +1134,7 @@ class RenewableCert(interfaces.RenewableCert): password=None, backend=default_backend() ) - return key + return cast(Union[RSAPrivateKey, EllipticCurvePrivateKey], key) @property def private_key_type(self) -> str: diff --git a/certbot/certbot/crypto_util.py b/certbot/certbot/crypto_util.py index 4e95fd11b..d0240aefd 100644 --- a/certbot/certbot/crypto_util.py +++ b/certbot/certbot/crypto_util.py @@ -45,6 +45,8 @@ from certbot.compat import os if TYPE_CHECKING: from cryptography.hazmat.primitives.asymmetric.ed448 import Ed448PublicKey from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey + from cryptography.hazmat.primitives.asymmetric.x448 import X448PublicKey + from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PublicKey logger = logging.getLogger(__name__) @@ -243,11 +245,7 @@ def make_key(bits: int = 1024, key_type: str = "rsa", raise errors.Error("Unsupported elliptic curve: {}".format(elliptic_curve)) except UnsupportedAlgorithm as e: raise e from errors.Error(str(e)) - # This type ignore directive is required due to an outdated version of types-cryptography. - # It can be removed once package types-pyOpenSSL depends on cryptography instead of - # types-cryptography and so types-cryptography is not installed anymore. - # See https://github.com/python/typeshed/issues/5618 - _key_pem = _key.private_bytes( # type: ignore + _key_pem = _key.private_bytes( encoding=Encoding.PEM, format=PrivateFormat.TraditionalOpenSSL, encryption_algorithm=NoEncryption() @@ -306,6 +304,7 @@ def verify_renewable_cert_sig(renewable_cert: interfaces.RenewableCert) -> None: with open(renewable_cert.cert_path, 'rb') as cert_file: cert = x509.load_pem_x509_certificate(cert_file.read(), default_backend()) pk = chain.public_key() + assert cert.signature_hash_algorithm # always present for RSA and ECDSA verify_signed_payload(pk, cert.signature, cert.tbs_certificate_bytes, cert.signature_hash_algorithm) except (IOError, ValueError, InvalidSignature) as e: @@ -316,7 +315,8 @@ def verify_renewable_cert_sig(renewable_cert: interfaces.RenewableCert) -> None: def verify_signed_payload(public_key: Union[DSAPublicKey, 'Ed25519PublicKey', 'Ed448PublicKey', - EllipticCurvePublicKey, RSAPublicKey], + EllipticCurvePublicKey, RSAPublicKey, + 'X25519PublicKey', 'X448PublicKey'], signature: bytes, payload: bytes, signature_hash_algorithm: hashes.HashAlgorithm) -> None: """Check the signature of a payload. diff --git a/certbot/certbot/ocsp.py b/certbot/certbot/ocsp.py index 2a51fe834..0278adef7 100644 --- a/certbot/certbot/ocsp.py +++ b/certbot/certbot/ocsp.py @@ -285,6 +285,7 @@ def _check_ocsp_response_signature(response_ocsp: 'ocsp.OCSPResponse', # Following line may raise UnsupportedAlgorithm chosen_cert_hash = responder_cert.signature_hash_algorithm + assert chosen_cert_hash # always present for RSA and ECDSA certificates. # For a delegate OCSP responder, we need first check that its certificate is effectively # signed by the certificate issuer. crypto_util.verify_signed_payload(issuer_cert.public_key(), responder_cert.signature, diff --git a/certbot/certbot/tests/util.py b/certbot/certbot/tests/util.py index 772fcd5a5..c7bbbb422 100644 --- a/certbot/certbot/tests/util.py +++ b/certbot/certbot/tests/util.py @@ -20,6 +20,7 @@ from unittest import mock from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey import josepy as jose from OpenSSL import crypto import pkg_resources @@ -128,8 +129,9 @@ def load_rsa_private_key(*names: str) -> jose.ComparableRSAKey: loader_fn = serialization.load_pem_private_key else: loader_fn = serialization.load_der_private_key - return jose.ComparableRSAKey(loader_fn( - load_vector(*names), password=None, backend=default_backend())) + return jose.ComparableRSAKey( + cast(RSAPrivateKey, + loader_fn(load_vector(*names), password=None, backend=default_backend()))) def load_pyopenssl_private_key(*names: str) -> crypto.PKey: diff --git a/tools/requirements.txt b/tools/requirements.txt index 37630073a..45db89e65 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -5,65 +5,64 @@ # requirements.txt so that is scanned by GitHub. See # https://docs.github.com/en/github/visualizing-repository-data-with-graphs/about-the-dependency-graph#supported-package-ecosystems # for more info. -alabaster==0.7.12 ; python_version >= "3.7" and python_version < "4.0" +alabaster==0.7.13 ; python_version >= "3.7" and python_version < "4.0" apacheconfig==0.3.2 ; python_version >= "3.7" and python_version < "4.0" appnope==0.1.3 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "darwin" -astroid==2.12.13 ; python_full_version >= "3.7.2" and python_version < "4.0" +astroid==2.13.5 ; python_full_version >= "3.7.2" and python_version < "4.0" attrs==22.2.0 ; python_version >= "3.7" and python_version < "4.0" azure-devops==6.0.0b4 ; python_version >= "3.7" and python_version < "4.0" babel==2.11.0 ; python_version >= "3.7" and python_version < "4.0" backcall==0.2.0 ; python_version >= "3.7" and python_version < "4.0" backports-cached-property==1.0.2 ; python_version >= "3.7" and python_version < "3.8" bcrypt==4.0.1 ; python_version >= "3.7" and python_version < "4.0" -beautifulsoup4==4.11.1 ; python_version >= "3.7" and python_version < "4.0" -bleach==5.0.1 ; python_version >= "3.7" and python_version < "4.0" -boto3==1.26.42 ; python_version >= "3.7" and python_version < "4.0" -botocore==1.29.42 ; python_version >= "3.7" and python_version < "4.0" +beautifulsoup4==4.11.2 ; python_version >= "3.7" and python_version < "4.0" +bleach==6.0.0 ; python_version >= "3.7" and python_version < "4.0" +boto3==1.26.65 ; python_version >= "3.7" and python_version < "4.0" +botocore==1.29.65 ; python_version >= "3.7" and python_version < "4.0" cachecontrol==0.12.11 ; python_version >= "3.7" and python_version < "4.0" -cachetools==5.2.0 ; python_version >= "3.7" and python_version < "4.0" +cachetools==5.3.0 ; python_version >= "3.7" and python_version < "4.0" cachy==0.3.0 ; python_version >= "3.7" and python_version < "4.0" certifi==2022.12.7 ; python_version >= "3.7" and python_version < "4" cffi==1.15.1 ; python_version >= "3.7" and python_version < "4.0" -charset-normalizer==2.1.1 ; python_version >= "3.7" and python_version < "4" +charset-normalizer==3.0.1 ; python_version >= "3.7" and python_version < "4" cleo==1.0.0a5 ; python_version >= "3.7" and python_version < "4.0" cloudflare==2.11.1 ; python_version >= "3.7" and python_version < "4.0" colorama==0.4.6 ; python_version < "4.0" and sys_platform == "win32" and python_version >= "3.7" or python_version >= "3.7" and python_version < "4.0" and platform_system == "Windows" -commonmark==0.9.1 ; python_version >= "3.7" and python_version < "4.0" configargparse==1.5.3 ; python_version >= "3.7" and python_version < "4.0" -configobj==5.0.6 ; python_version >= "3.7" and python_version < "4.0" -coverage==7.0.3 ; python_version >= "3.7" and python_version < "4.0" +configobj==5.0.8 ; python_version >= "3.7" and python_version < "4.0" +coverage==7.1.0 ; python_version >= "3.7" and python_version < "4.0" crashtest==0.3.1 ; python_version >= "3.7" and python_version < "4.0" -cryptography==39.0.0 ; python_version >= "3.7" and python_version < "4.0" -cython==0.29.32 ; python_version >= "3.7" and python_version < "4.0" +cryptography==39.0.1 ; python_version >= "3.7" and python_version < "4.0" +cython==0.29.33 ; python_version >= "3.7" and python_version < "4.0" decorator==5.1.1 ; python_version >= "3.7" and python_version < "4.0" dill==0.3.6 ; python_full_version >= "3.7.2" and python_version < "4.0" distlib==0.3.6 ; python_version >= "3.7" and python_version < "4.0" distro==1.8.0 ; python_version >= "3.7" and python_version < "4.0" dns-lexicon==3.11.7 ; python_version >= "3.7" and python_version < "4.0" -dnspython==2.2.1 ; python_version >= "3.7" and python_version < "4.0" +dnspython==2.3.0 ; python_version >= "3.7" and python_version < "4.0" docutils==0.17.1 ; python_version >= "3.7" and python_version < "4.0" dulwich==0.20.50 ; python_version >= "3.7" and python_version < "4.0" exceptiongroup==1.1.0 ; python_version >= "3.7" and python_version < "3.11" execnet==1.9.0 ; python_version >= "3.7" and python_version < "4.0" -fabric==2.7.1 ; python_version >= "3.7" and python_version < "4.0" +fabric==3.0.0 ; python_version >= "3.7" and python_version < "4.0" filelock==3.9.0 ; python_version >= "3.7" and python_version < "4.0" google-api-core==2.11.0 ; python_version >= "3.7" and python_version < "4.0" -google-api-python-client==2.70.0 ; python_version >= "3.7" and python_version < "4.0" +google-api-python-client==2.77.0 ; python_version >= "3.7" and python_version < "4.0" google-auth-httplib2==0.1.0 ; python_version >= "3.7" and python_version < "4.0" -google-auth==2.15.0 ; python_version >= "3.7" and python_version < "4.0" -googleapis-common-protos==1.57.0 ; python_version >= "3.7" and python_version < "4.0" +google-auth==2.16.0 ; python_version >= "3.7" and python_version < "4.0" +googleapis-common-protos==1.58.0 ; python_version >= "3.7" and python_version < "4.0" html5lib==1.1 ; python_version >= "3.7" and python_version < "4.0" httplib2==0.21.0 ; python_version >= "3.7" and python_version < "4.0" idna==3.4 ; python_version >= "3.7" and python_version < "4" imagesize==1.4.1 ; python_version >= "3.7" and python_version < "4.0" importlib-metadata==4.13.0 ; python_version >= "3.7" and python_version < "4.0" importlib-resources==5.10.2 ; python_version >= "3.7" and python_version < "3.9" -iniconfig==1.1.1 ; python_version >= "3.7" and python_version < "4.0" -invoke==1.7.3 ; python_version >= "3.7" and python_version < "4.0" +iniconfig==2.0.0 ; python_version >= "3.7" and python_version < "4.0" +invoke==2.0.0 ; python_version >= "3.7" and python_version < "4.0" ipdb==0.13.11 ; python_version >= "3.7" and python_version < "4.0" ipython==7.34.0 ; python_version >= "3.7" and python_version < "4.0" isodate==0.6.1 ; python_version >= "3.7" and python_version < "4.0" -isort==5.11.4 ; python_full_version >= "3.7.2" and python_version < "4.0" +isort==5.11.5 ; python_full_version >= "3.7.2" and python_version < "4.0" jaraco-classes==3.2.3 ; python_version >= "3.7" and python_version < "4.0" jedi==0.18.2 ; python_version >= "3.7" and python_version < "4.0" jeepney==0.8.0 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux" @@ -74,27 +73,28 @@ jsonlines==3.1.0 ; python_version >= "3.7" and python_version < "4.0" jsonpickle==3.0.1 ; python_version >= "3.7" and python_version < "4.0" jsonschema==4.17.3 ; python_version >= "3.7" and python_version < "4.0" keyring==23.13.1 ; python_version >= "3.7" and python_version < "4.0" -lazy-object-proxy==1.8.0 ; python_full_version >= "3.7.2" and python_version < "4.0" +lazy-object-proxy==1.9.0 ; python_full_version >= "3.7.2" and python_version < "4.0" lockfile==0.12.2 ; python_version >= "3.7" and python_version < "4.0" -markupsafe==2.1.1 ; python_version >= "3.7" and python_version < "4.0" +markdown-it-py==2.1.0 ; python_version >= "3.7" and python_version < "4.0" +markupsafe==2.1.2 ; python_version >= "3.7" and python_version < "4.0" matplotlib-inline==0.1.6 ; python_version >= "3.7" and python_version < "4.0" mccabe==0.7.0 ; python_full_version >= "3.7.2" and python_version < "4.0" +mdurl==0.1.2 ; python_version >= "3.7" and python_version < "4.0" more-itertools==9.0.0 ; python_version >= "3.7" and python_version < "4.0" msgpack==1.0.4 ; python_version >= "3.7" and python_version < "4.0" msrest==0.6.21 ; python_version >= "3.7" and python_version < "4.0" -mypy-extensions==0.4.3 ; python_version >= "3.7" and python_version < "4.0" -mypy==0.991 ; python_version >= "3.7" and python_version < "4.0" +mypy-extensions==1.0.0 ; python_version >= "3.7" and python_version < "4.0" +mypy==1.0.0 ; python_version >= "3.7" and python_version < "4.0" oauth2client==4.1.3 ; python_version >= "3.7" and python_version < "4.0" oauthlib==3.2.2 ; python_version >= "3.7" and python_version < "4.0" -packaging==22.0 ; python_version >= "3.7" and python_version < "4.0" -paramiko==2.12.0 ; python_version >= "3.7" and python_version < "4.0" +packaging==23.0 ; python_version >= "3.7" and python_version < "4.0" +paramiko==3.0.0 ; python_version >= "3.7" and python_version < "4.0" parsedatetime==2.6 ; python_version >= "3.7" and python_version < "4.0" parso==0.8.3 ; python_version >= "3.7" and python_version < "4.0" -pathlib2==2.3.7.post1 ; python_version >= "3.7" and python_version < "4.0" pexpect==4.8.0 ; python_version >= "3.7" and python_version < "4.0" pickleshare==0.7.5 ; python_version >= "3.7" and python_version < "4.0" -pip==22.3.1 ; python_version >= "3.7" and python_version < "4.0" -pkginfo==1.9.3 ; python_version >= "3.7" and python_version < "4.0" +pip==23.0 ; python_version >= "3.7" and python_version < "4.0" +pkginfo==1.9.6 ; python_version >= "3.7" and python_version < "4.0" pkgutil-resolve-name==1.3.10 ; python_version >= "3.7" and python_version < "3.9" platformdirs==2.6.2 ; python_version < "4.0" and python_version >= "3.7" pluggy==1.0.0 ; python_version >= "3.7" and python_version < "4.0" @@ -119,12 +119,12 @@ pyparsing==3.0.9 ; python_version >= "3.7" and python_version < "4.0" pyrfc3339==1.1 ; python_version >= "3.7" and python_version < "4.0" pyrsistent==0.19.3 ; python_version >= "3.7" and python_version < "4.0" pytest-cov==4.0.0 ; python_version >= "3.7" and python_version < "4.0" -pytest-xdist==3.1.0 ; python_version >= "3.7" and python_version < "4.0" -pytest==7.2.0 ; python_version >= "3.7" and python_version < "4.0" +pytest-xdist==3.2.0 ; python_version >= "3.7" and python_version < "4.0" +pytest==7.2.1 ; python_version >= "3.7" and python_version < "4.0" python-augeas==1.1.0 ; python_version >= "3.7" and python_version < "4.0" python-dateutil==2.8.2 ; python_version >= "3.7" and python_version < "4.0" python-digitalocean==1.17.0 ; python_version >= "3.7" and python_version < "4.0" -pytz==2022.7 ; python_version >= "3.7" and python_version < "4.0" +pytz==2022.7.1 ; python_version >= "3.7" and python_version < "4.0" pywin32-ctypes==0.2.0 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "win32" pywin32==305 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "win32" pyyaml==6.0 ; python_version >= "3.7" and python_version < "4.0" @@ -133,15 +133,15 @@ requests-download==0.1.2 ; python_version >= "3.7" and python_version < "4.0" requests-file==1.5.1 ; python_version >= "3.7" and python_version < "4.0" requests-oauthlib==1.3.1 ; python_version >= "3.7" and python_version < "4.0" requests-toolbelt==0.9.1 ; python_version >= "3.7" and python_version < "4.0" -requests==2.28.1 ; python_version >= "3.7" and python_version < "4" +requests==2.28.2 ; python_version >= "3.7" and python_version < "4" rfc3986==2.0.0 ; python_version >= "3.7" and python_version < "4.0" -rich==13.0.0 ; python_version >= "3.7" and python_version < "4.0" +rich==13.3.1 ; python_version >= "3.7" and python_version < "4.0" rsa==4.9 ; python_version >= "3.7" and python_version < "4" s3transfer==0.6.0 ; python_version >= "3.7" and python_version < "4.0" secretstorage==3.3.3 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux" semantic-version==2.10.0 ; python_version >= "3.7" and python_version < "4.0" setuptools-rust==1.5.2 ; python_version >= "3.7" and python_version < "4.0" -setuptools==65.6.3 ; python_version >= "3.7" and python_version < "4.0" +setuptools==67.2.0 ; python_version >= "3.7" and python_version < "4.0" shellingham==1.5.0.post1 ; python_version >= "3.7" and python_version < "4.0" six==1.16.0 ; python_version >= "3.7" and python_version < "4.0" snowballstemmer==2.2.0 ; python_version >= "3.7" and python_version < "4.0" @@ -158,26 +158,26 @@ tldextract==3.4.0 ; python_version >= "3.7" and python_version < "4.0" tomli==2.0.1 ; python_version >= "3.7" and python_full_version <= "3.11.0a6" tomlkit==0.11.6 ; python_version < "4.0" and python_version >= "3.7" tox==3.28.0 ; python_version >= "3.7" and python_version < "4.0" -traitlets==5.8.0 ; python_version >= "3.7" and python_version < "4.0" +traitlets==5.9.0 ; python_version >= "3.7" and python_version < "4.0" twine==4.0.2 ; python_version >= "3.7" and python_version < "4.0" typed-ast==1.5.4 ; python_version < "3.8" and python_version >= "3.7" -types-cryptography==3.3.23.2 ; python_version >= "3.7" and python_version < "4.0" -types-pyopenssl==23.0.0.0 ; python_version >= "3.7" and python_version < "4.0" +types-docutils==0.19.1.3 ; python_version >= "3.7" and python_version < "4.0" +types-pyopenssl==23.0.0.2 ; python_version >= "3.7" and python_version < "4.0" types-pyrfc3339==1.1.1.1 ; python_version >= "3.7" and python_version < "4.0" -types-python-dateutil==2.8.19.5 ; python_version >= "3.7" and python_version < "4.0" -types-pytz==2022.7.0.0 ; python_version >= "3.7" and python_version < "4.0" -types-requests==2.28.11.7 ; python_version >= "3.7" and python_version < "4.0" -types-setuptools==65.6.0.2 ; python_version >= "3.7" and python_version < "4.0" +types-python-dateutil==2.8.19.6 ; python_version >= "3.7" and python_version < "4.0" +types-pytz==2022.7.1.0 ; python_version >= "3.7" and python_version < "4.0" +types-requests==2.28.11.12 ; python_version >= "3.7" and python_version < "4.0" +types-setuptools==67.1.0.2 ; python_version >= "3.7" and python_version < "4.0" types-six==1.16.21.4 ; python_version >= "3.7" and python_version < "4.0" -types-urllib3==1.26.25.4 ; python_version >= "3.7" and python_version < "4.0" +types-urllib3==1.26.25.5 ; python_version >= "3.7" and python_version < "4.0" typing-extensions==4.4.0 ; python_version >= "3.7" and python_version < "4.0" uritemplate==4.1.1 ; python_version >= "3.7" and python_version < "4.0" -urllib3==1.26.13 ; python_version >= "3.7" and python_version < "4.0" -virtualenv==20.17.1 ; python_version >= "3.7" and python_version < "4.0" -wcwidth==0.2.5 ; python_version >= "3.7" and python_version < "4.0" +urllib3==1.26.14 ; python_version >= "3.7" and python_version < "4.0" +virtualenv==20.18.0 ; python_version >= "3.7" and python_version < "4.0" +wcwidth==0.2.6 ; python_version >= "3.7" and python_version < "4.0" webencodings==0.5.1 ; python_version >= "3.7" and python_version < "4.0" wheel==0.38.4 ; python_version >= "3.7" and python_version < "4.0" wrapt==1.14.1 ; python_full_version >= "3.7.2" and python_version < "4.0" xattr==0.9.9 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "darwin" yarg==0.1.9 ; python_version >= "3.7" and python_version < "4.0" -zipp==3.11.0 ; python_version >= "3.7" and python_version < "4.0" +zipp==3.12.1 ; python_version >= "3.7" and python_version < "4.0" From cd9ee996a812bc963e5fe1c9ddcafcabfc792059 Mon Sep 17 00:00:00 2001 From: Alexis Date: Wed, 8 Feb 2023 12:12:15 -0800 Subject: [PATCH 21/57] Create SECURITY.md (#9566) --- SECURITY.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..f9c1e57b1 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,5 @@ +# Security Policy + +## Reporting a Vulnerability + +Security vulnerabilities can be reported using GitHub's [private vulnerability reporting tool](https://github.com/certbot/certbot/security/advisories/new). From f5ea5d453e6708eae429a8fc0f4768e73c53c971 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 8 Feb 2023 14:21:07 -0800 Subject: [PATCH 22/57] fix requests-toolbelt warning (#9569) --- pytest.ini | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pytest.ini b/pytest.ini index e498766ec..b0c4fe1dc 100644 --- a/pytest.ini +++ b/pytest.ini @@ -15,7 +15,12 @@ # certbot-dns-rfc2136. # 2) pytest-cov uses deprecated functionality in pytest-xdist, to be resolved by # https://github.com/pytest-dev/pytest-cov/issues/557. +# 3) requests-toolbelt<0.10.1 can cause this warning to be raised during our +# unit tests. This warning should be ignored until our (transitive) +# dependency on requests-toolbelt is removed or our pinned version can be +# updated. filterwarnings = error ignore:decodestring\(\) is a deprecated alias:DeprecationWarning:dns ignore:.*rsyncdir:DeprecationWarning + ignore:'urllib3.contrib.pyopenssl:DeprecationWarning:requests_toolbelt From d792d398134f4f8b67debaf82e6e75635409c627 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 8 Feb 2023 14:24:07 -0800 Subject: [PATCH 23/57] reset set_by_cli between each test (#9567) --- certbot/tests/conftest.py | 7 +++++++ certbot/tests/main_test.py | 2 -- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 certbot/tests/conftest.py diff --git a/certbot/tests/conftest.py b/certbot/tests/conftest.py new file mode 100644 index 000000000..191e07b55 --- /dev/null +++ b/certbot/tests/conftest.py @@ -0,0 +1,7 @@ +import pytest + +from certbot._internal import cli + +@pytest.fixture(autouse=True) +def reset_cli_global(): + cli.set_by_cli.detector = None diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index 4b416272f..0eae761a2 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -422,7 +422,6 @@ class RevokeTest(test_util.TempDirTestCase): if not args: args = 'revoke --cert-path={0} ' args = args.format(self.tmp_cert_path).split() - cli.set_by_cli.detector = None # required to reset set_by_cli state plugins = disco.PluginsRegistry.find_all() config = configuration.NamespaceConfig( cli.prepare_and_parse_args(plugins, args)) @@ -588,7 +587,6 @@ class ReconfigureTest(test_util.TempDirTestCase): def _call(self, passed_args): full_args = passed_args + ['--config-dir', self.config_dir] - cli.set_by_cli.detector = None # required to reset set_by_cli state plugins = disco.PluginsRegistry.find_all() config = configuration.NamespaceConfig( cli.prepare_and_parse_args(plugins, full_args)) From 99956ecab9c948f32fe41262b0f88f996c9556f4 Mon Sep 17 00:00:00 2001 From: ohemorange Date: Wed, 8 Feb 2023 16:16:28 -0800 Subject: [PATCH 24/57] Fix typo direcory --> directory in --run-deploy-hooks help (#9568) --- certbot/certbot/_internal/cli/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot/certbot/_internal/cli/__init__.py b/certbot/certbot/_internal/cli/__init__.py index bb4f0eaa1..2719f0641 100644 --- a/certbot/certbot/_internal/cli/__init__.py +++ b/certbot/certbot/_internal/cli/__init__.py @@ -164,7 +164,7 @@ def prepare_and_parse_args(plugins: plugins_disco.PluginsRegistry, args: List[st help="When performing a test run using `--dry-run` or `reconfigure`, run any applicable" " deploy hooks. This includes hooks set on the command line, saved in the" " certificate's renewal configuration file, or present in the renewal-hooks directory." - " To exclude direcory hooks, use --no-directory-hooks. The hook(s) will only" + " To exclude directory hooks, use --no-directory-hooks. The hook(s) will only" " be run if the dry run succeeds, and will use the current active certificate, not" " the temporary test certificate acquired during the dry run. This flag is recommended" " when modifying the deploy hook using `reconfigure`.") From cbb4c871c2074460e288b792b3ede4ad8a172a8d Mon Sep 17 00:00:00 2001 From: alexzorin Date: Thu, 9 Feb 2023 13:14:32 +1100 Subject: [PATCH 25/57] docs: document reconfigure verb (#9563) * docs: document reconfigure verb * expand on the flags relevant to reconfigure * Update phrasing Co-authored-by: ohemorange --------- Co-authored-by: ohemorange --- certbot/docs/using.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/certbot/docs/using.rst b/certbot/docs/using.rst index 359119f0c..1ef649906 100644 --- a/certbot/docs/using.rst +++ b/certbot/docs/using.rst @@ -751,6 +751,26 @@ time, Certbot will remember these options and apply them once again. Sometimes, you may encounter the need to change some of these options for future certificate renewals. To achieve this, you will need to perform the following steps: +Certbot v2.3.0 and newer +~~~~~~~~~~~~~~~~~~~~~~~~ +The ``certbot reconfigure`` command can be used to change a certificate's renewal options. +This command will use the new renewal options to perform a test renewal against the Let's Encrypt staging server. +If this is successful, the new renewal options will be saved and will apply to future renewals. + +You will need to specify the ``--cert-name``, which can be found by running ``certbot certificates``. + +A list of common options that may be updated with the ``reconfigure`` command can be found by running +``certbot help reconfigure``. + +As a practical example, if you were using the ``webroot`` authenticator and had relocated your website to another directory, +you can change the ``--webroot-path`` to the new directory using the following command: + +.. code-block:: shell + + certbot reconfigure --cert-name example.com --webroot-path /path/to/new/location + +Certbot v2.2.0 and older +~~~~~~~~~~~~~~~~~~~~~~~~ 1. Perform a *dry run renewal* with the amended options on the command line. This allows you to confirm that the change is valid and will result in successful future renewals. 2. If the dry run is successful, perform a *live renewal* of the certificate. This will persist the change for future From aac02bef35ecadda978d067319fbd88f6f249eeb Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 8 Feb 2023 20:55:59 -0800 Subject: [PATCH 26/57] Remove code testing testing code --- .../validator_test.py | 129 ------------------ 1 file changed, 129 deletions(-) delete mode 100644 certbot-compatibility-test/certbot_compatibility_test/validator_test.py diff --git a/certbot-compatibility-test/certbot_compatibility_test/validator_test.py b/certbot-compatibility-test/certbot_compatibility_test/validator_test.py deleted file mode 100644 index 1a2d4dfb5..000000000 --- a/certbot-compatibility-test/certbot_compatibility_test/validator_test.py +++ /dev/null @@ -1,129 +0,0 @@ -"""Tests for certbot_compatibility_test.validator.""" -from typing import cast -from typing import Mapping -from typing import Optional -import unittest -from unittest import mock - -from certbot_compatibility_test import validator -from OpenSSL import crypto -import requests - -from acme import errors as acme_errors - - -class ValidatorTest(unittest.TestCase): - def setUp(self) -> None: - self.validator = validator.Validator() - - @mock.patch( - "certbot_compatibility_test.validator.crypto_util.probe_sni") - def test_certificate_success(self, mock_probe_sni: mock.MagicMock) -> None: - cert = crypto.X509() - mock_probe_sni.return_value = cert - self.assertTrue(self.validator.certificate( - cert, "test.com", "127.0.0.1")) - - @mock.patch( - "certbot_compatibility_test.validator.crypto_util.probe_sni") - def test_certificate_error(self, mock_probe_sni: mock.MagicMock) -> None: - cert = crypto.X509() - mock_probe_sni.side_effect = [acme_errors.Error] - self.assertFalse(self.validator.certificate( - cert, "test.com", "127.0.0.1")) - - @mock.patch( - "certbot_compatibility_test.validator.crypto_util.probe_sni") - def test_certificate_failure(self, mock_probe_sni: mock.MagicMock) -> None: - cert = crypto.X509() - cert.set_serial_number(1337) - mock_probe_sni.return_value = crypto.X509() - self.assertFalse(self.validator.certificate( - cert, "test.com", "127.0.0.1")) - - @mock.patch("certbot_compatibility_test.validator.requests.get") - def test_successful_redirect(self, mock_get_request: mock.MagicMock) -> None: - mock_get_request.return_value = create_response( - 301, {"location": "https://test.com"}) - self.assertTrue(self.validator.redirect("test.com")) - - @mock.patch("certbot_compatibility_test.validator.requests.get") - def test_redirect_with_headers(self, mock_get_request: mock.MagicMock) -> None: - mock_get_request.return_value = create_response( - 301, {"location": "https://test.com"}) - self.assertTrue(self.validator.redirect( - "test.com", headers={"Host": "test.com"})) - - @mock.patch("certbot_compatibility_test.validator.requests.get") - def test_redirect_missing_location(self, mock_get_request: mock.MagicMock) -> None: - mock_get_request.return_value = create_response(301) - self.assertFalse(self.validator.redirect("test.com")) - - @mock.patch("certbot_compatibility_test.validator.requests.get") - def test_redirect_wrong_status_code(self, mock_get_request: mock.MagicMock) -> None: - mock_get_request.return_value = create_response( - 201, {"location": "https://test.com"}) - self.assertFalse(self.validator.redirect("test.com")) - - @mock.patch("certbot_compatibility_test.validator.requests.get") - def test_redirect_wrong_redirect_code(self, mock_get_request: mock.MagicMock) -> None: - mock_get_request.return_value = create_response( - 303, {"location": "https://test.com"}) - self.assertFalse(self.validator.redirect("test.com")) - - @mock.patch("certbot_compatibility_test.validator.requests.get") - def test_hsts_empty(self, mock_get_request: mock.MagicMock) -> None: - mock_get_request.return_value = create_response( - headers={"strict-transport-security": ""}) - self.assertFalse(self.validator.hsts("test.com")) - - @mock.patch("certbot_compatibility_test.validator.requests.get") - def test_hsts_malformed(self, mock_get_request: mock.MagicMock) -> None: - mock_get_request.return_value = create_response( - headers={"strict-transport-security": "sdfal"}) - self.assertFalse(self.validator.hsts("test.com")) - - @mock.patch("certbot_compatibility_test.validator.requests.get") - def test_hsts_bad_max_age(self, mock_get_request: mock.MagicMock) -> None: - mock_get_request.return_value = create_response( - headers={"strict-transport-security": "max-age=not-an-int"}) - self.assertFalse(self.validator.hsts("test.com")) - - @mock.patch("certbot_compatibility_test.validator.requests.get") - def test_hsts_expire(self, mock_get_request: mock.MagicMock) -> None: - mock_get_request.return_value = create_response( - headers={"strict-transport-security": "max-age=3600"}) - self.assertFalse(self.validator.hsts("test.com")) - - @mock.patch("certbot_compatibility_test.validator.requests.get") - def test_hsts(self, mock_get_request: mock.MagicMock) -> None: - mock_get_request.return_value = create_response( - headers={"strict-transport-security": "max-age=31536000"}) - self.assertTrue(self.validator.hsts("test.com")) - - @mock.patch("certbot_compatibility_test.validator.requests.get") - def test_hsts_include_subdomains(self, mock_get_request: mock.MagicMock) -> None: - mock_get_request.return_value = create_response( - headers={"strict-transport-security": - "max-age=31536000;includeSubDomains"}) - self.assertTrue(self.validator.hsts("test.com")) - - def test_ocsp_stapling(self) -> None: - self.assertRaises( - NotImplementedError, self.validator.ocsp_stapling, "test.com") - - -def create_response(status_code: int = 200, - headers: Optional[Mapping[str, str]] = None) -> requests.Response: - """Creates a requests.Response object for testing""" - response = requests.Response() - response.status_code = status_code - - if headers: - response.headers = cast(requests.models.CaseInsensitiveDict, headers) - - return response - - -if __name__ == '__main__': - unittest.main() # pragma: no cover From 3512d15dff99e8b76bd97245cfba9a5122a4171c Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 9 Feb 2023 18:41:16 -0800 Subject: [PATCH 27/57] Remove most progressive release tooling --- tools/finish_release.py | 40 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/tools/finish_release.py b/tools/finish_release.py index 88db47105..8d720bc60 100755 --- a/tools/finish_release.py +++ b/tools/finish_release.py @@ -4,7 +4,7 @@ Post-release script to publish artifacts created from Azure Pipelines. This currently includes: -* Moving snaps from the candidate/beta channel to the stable channel +* Moving snaps from the beta channel to the stable channel * Publishing the Windows installer in a GitHub release Setup: @@ -40,16 +40,20 @@ import requests # Path to the root directory of the Certbot repository containing this script REPO_ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) -# This list contains the names of all Certbot DNS plugins -PLUGIN_SNAPS = [os.path.basename(path) for path in glob.glob(os.path.join(REPO_ROOT, 'certbot-dns-*'))] +# This list contains the names of all Certbot DNS plugins. We used to have a +# CloudXNS plugin and since it's possible devs still have that directory +# locally, we filter it out here. If it's included in this list, this script +# will crash later when it fails to find a CloudXNS snap on the snap store with +# the current version since we no longer build it. +PLUGIN_SNAPS = [os.path.basename(path) + for path in glob.glob(os.path.join(REPO_ROOT, 'certbot-dns-*')) + if 'cloudxns' not in path] # This list contains the name of all Certbot snaps that should be published to # the stable channel. ALL_SNAPS = ['certbot'] + PLUGIN_SNAPS # This is the count of the architectures currently supported by our snaps used # for sanity checking. SNAP_ARCH_COUNT = 3 -# The percentage of users the 2.0 Certbot snap should be deployed to. -PROGRESSIVE_RELEASE_PERCENTAGE = 10 def parse_args(args): @@ -66,8 +70,7 @@ def parse_args(args): # Use the file's docstring for the help text and don't let argparse reformat it. parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) - parser.add_argument('--css', type=str, help='hostname of code signing server') - parser.add_argument('--progressive-only', action='store_true', help='only do a Certbot 2.0 progressive snap release') + parser.add_argument('--css', type=str, required=True, help='hostname of code signing server') return parser.parse_args(args) @@ -171,7 +174,7 @@ def promote_snaps(snaps, source_channel, version, progressive_percentage=None): print(e.stdout) raise -def fetch_version_number(major_version): +def fetch_version_number(major_version=None): """Retrieve version number for release from Azure Pipelines :param major_version: only consider releases for the specified major @@ -198,29 +201,14 @@ def main(args): parsed_args = parse_args(args) css = parsed_args.css - version = fetch_version_number('2' if parsed_args.progressive_only else None) + version = fetch_version_number() # Once the GitHub release has been published, trying to publish it # again fails. Publishing the snaps can be done multiple times though # so we do that first to make it easier to run the script again later # if something goes wrong. - # - # We only publish all snaps to the stable channel for 1.x releases. For 2.x - # releases, we only progressively release the base Certbot snap and update - # the Windows installer. Once we feel confident enough about Certbot 2.x, - # we should stop doing 1.x releases and unconditionally publish all snaps - # and the Windows installer. - if version.startswith('1.'): - promote_snaps(ALL_SNAPS, 'candidate', version) - elif not parsed_args.progressive_only and parsed_args.css is None: - # Fail fast if we weren't given a --css argument because we're going to - # need it later. - raise ValueError('Please provide the --css command line argument') - else: - promote_snaps(['certbot'], 'beta', version, - progressive_percentage=PROGRESSIVE_RELEASE_PERCENTAGE) - if not parsed_args.progressive_only: - publish_windows(css) + promote_snaps(ALL_SNAPS, 'beta', version) + publish_windows(css) if __name__ == "__main__": main(sys.argv[1:]) From f91d3ca828cf60402109c1b3eae4bbcf399438a5 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 9 Feb 2023 18:42:41 -0800 Subject: [PATCH 28/57] remove 1.32.x deps --- certbot/docs/contributing.rst | 10 +- tools/1.32.x/requirements.txt | 194 ---------------------------------- 2 files changed, 2 insertions(+), 202 deletions(-) delete mode 100644 tools/1.32.x/requirements.txt diff --git a/certbot/docs/contributing.rst b/certbot/docs/contributing.rst index 49cc1fc81..f86bed01a 100644 --- a/certbot/docs/contributing.rst +++ b/certbot/docs/contributing.rst @@ -585,8 +585,8 @@ include our snaps, Docker images, Windows installer, CI, and our development environments. In most cases, the file where dependency versions are specified is -``tools/requirements.txt``. There are three exceptions to this. The first is -our "oldest" tests where ``tools/oldest_constraints.txt`` is used instead. The +``tools/requirements.txt``. There are two exceptions to this. The first is our +"oldest" tests where ``tools/oldest_constraints.txt`` is used instead. The purpose of the "oldest" tests is to ensure Certbot continues to work with the oldest versions of our dependencies which we claim to support. The oldest versions of the dependencies we support should also be declared in our setup.py @@ -598,12 +598,6 @@ leave Certbot's dependencies unpinned. The thinking behind this test is to help us learn about breaking changes in our dependencies so that we can respond accordingly. -The third exception is temporary and at ``tools/1.32.x/requirements.txt``. -This file is simply a copy of ``tools/requirements.txt`` from our 1.32.x branch -to help us ensure those dependencies stay reasonably well updated while we still -have Certbot 1.x snap users. Once we've moved all snap users to Certbot 2.0, -this file should be deleted. - The choices of whether Certbot's dependencies are pinned and what file is used if they are should be automatically handled for you most of the time by Certbot's tooling. The way it works though is ``tools/pip_install.py`` (which diff --git a/tools/1.32.x/requirements.txt b/tools/1.32.x/requirements.txt deleted file mode 100644 index 429eaf192..000000000 --- a/tools/1.32.x/requirements.txt +++ /dev/null @@ -1,194 +0,0 @@ -# This is a copy of tools/requirements.txt from the 1.32.x branch that I -# placed here so it will be in our master branch and GitHub will scan it for -# security vulnerabilities while we still have 1.x snap users. If we're notified -# about problems in our dependencies here and want to upgrade, we should do so -# by updating tools/requirements.txt on the 1.32.x branch, doing a point release -# from that branch, and copying any updates to tools/requirements.txt on that -# branch to this file on the master branch. -# -# This file is named requirements.txt so it is scanned by GitHub. See -# https://docs.github.com/en/github/visualizing-repository-data-with-graphs/about-the-dependency-graph#supported-package-ecosystems -# for more info. -alabaster==0.7.12 ; python_version >= "3.7" and python_version < "4.0" -apacheconfig==0.3.2 ; python_version >= "3.7" and python_version < "4.0" -appnope==0.1.3 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "darwin" -astroid==2.11.7 ; python_version >= "3.7" and python_version < "4.0" -attrs==22.1.0 ; python_version >= "3.7" and python_version < "4.0" -awscli==1.27.30 ; python_version >= "3.7" and python_version < "4.0" -azure-devops==6.0.0b4 ; python_version >= "3.7" and python_version < "4.0" -babel==2.11.0 ; python_version >= "3.7" and python_version < "4.0" -backcall==0.2.0 ; python_version >= "3.7" and python_version < "4.0" -backports-cached-property==1.0.2 ; python_version >= "3.7" and python_version < "3.8" -bcrypt==4.0.1 ; python_version >= "3.7" and python_version < "4.0" -beautifulsoup4==4.11.1 ; python_version >= "3.7" and python_version < "4.0" -bleach==5.0.1 ; python_version >= "3.7" and python_version < "4.0" -boto3==1.26.30 ; python_version >= "3.7" and python_version < "4.0" -botocore==1.29.30 ; python_version >= "3.7" and python_version < "4.0" -cachecontrol==0.12.11 ; python_version >= "3.7" and python_version < "4.0" -cachetools==5.2.0 ; python_version >= "3.7" and python_version < "4.0" -cachy==0.3.0 ; python_version >= "3.7" and python_version < "4.0" -certifi==2022.12.7 ; python_version >= "3.7" and python_version < "4" -cffi==1.15.1 ; python_version >= "3.7" and python_version < "4.0" -charset-normalizer==2.1.1 ; python_version >= "3.7" and python_version < "4" -cleo==1.0.0a5 ; python_version >= "3.7" and python_version < "4.0" -cloudflare==2.11.1 ; python_version >= "3.7" and python_version < "4.0" -colorama==0.4.4 ; python_version >= "3.7" and python_version < "4.0" -commonmark==0.9.1 ; python_version >= "3.7" and python_version < "4.0" -configargparse==1.5.3 ; python_version >= "3.7" and python_version < "4.0" -configobj==5.0.6 ; python_version >= "3.7" and python_version < "4.0" -coverage==6.5.0 ; python_version >= "3.7" and python_version < "4.0" -crashtest==0.3.1 ; python_version >= "3.7" and python_version < "4.0" -cryptography==38.0.4 ; python_version >= "3.7" and python_version < "4.0" -cython==0.29.32 ; python_version >= "3.7" and python_version < "4.0" -decorator==5.1.1 ; python_version >= "3.7" and python_version < "4.0" -dill==0.3.6 ; python_version >= "3.7" and python_version < "4.0" -distlib==0.3.6 ; python_version >= "3.7" and python_version < "4.0" -distro==1.8.0 ; python_version >= "3.7" and python_version < "4.0" -dns-lexicon==3.11.7 ; python_version >= "3.7" and python_version < "4.0" -dnspython==2.2.1 ; python_version >= "3.7" and python_version < "4.0" -docutils==0.16 ; python_version >= "3.7" and python_version < "4.0" -dulwich==0.20.50 ; python_version >= "3.7" and python_version < "4.0" -exceptiongroup==1.0.4 ; python_version >= "3.7" and python_version < "3.11" -execnet==1.9.0 ; python_version >= "3.7" and python_version < "4.0" -fabric==2.7.1 ; python_version >= "3.7" and python_version < "4.0" -filelock==3.8.2 ; python_version >= "3.7" and python_version < "4.0" -google-api-core==2.11.0 ; python_version >= "3.7" and python_version < "4.0" -google-api-python-client==2.70.0 ; python_version >= "3.7" and python_version < "4.0" -google-auth-httplib2==0.1.0 ; python_version >= "3.7" and python_version < "4.0" -google-auth==2.15.0 ; python_version >= "3.7" and python_version < "4.0" -googleapis-common-protos==1.57.0 ; python_version >= "3.7" and python_version < "4.0" -html5lib==1.1 ; python_version >= "3.7" and python_version < "4.0" -httplib2==0.21.0 ; python_version >= "3.7" and python_version < "4.0" -idna==3.4 ; python_version >= "3.7" and python_version < "4" -imagesize==1.4.1 ; python_version >= "3.7" and python_version < "4.0" -importlib-metadata==4.13.0 ; python_version >= "3.7" and python_version < "4.0" -importlib-resources==5.10.1 ; python_version >= "3.7" and python_version < "3.9" -iniconfig==1.1.1 ; python_version >= "3.7" and python_version < "4.0" -invoke==1.7.3 ; python_version >= "3.7" and python_version < "4.0" -ipdb==0.13.11 ; python_version >= "3.7" and python_version < "4.0" -ipython==7.34.0 ; python_version >= "3.7" and python_version < "4.0" -isodate==0.6.1 ; python_version >= "3.7" and python_version < "4.0" -isort==5.11.2 ; python_version >= "3.7" and python_version < "4.0" -jaraco-classes==3.2.3 ; python_version >= "3.7" and python_version < "4.0" -jedi==0.18.2 ; python_version >= "3.7" and python_version < "4.0" -jeepney==0.8.0 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux" -jinja2==3.1.2 ; python_version >= "3.7" and python_version < "4.0" -jmespath==1.0.1 ; python_version >= "3.7" and python_version < "4.0" -josepy==1.13.0 ; python_version >= "3.7" and python_version < "4.0" -jsonlines==3.1.0 ; python_version >= "3.7" and python_version < "4.0" -jsonpickle==2.2.0 ; python_version >= "3.7" and python_version < "4.0" -jsonschema==4.17.3 ; python_version >= "3.7" and python_version < "4.0" -keyring==23.11.0 ; python_version >= "3.7" and python_version < "4.0" -lazy-object-proxy==1.8.0 ; python_version >= "3.7" and python_version < "4.0" -lockfile==0.12.2 ; python_version >= "3.7" and python_version < "4.0" -markupsafe==2.1.1 ; python_version >= "3.7" and python_version < "4.0" -matplotlib-inline==0.1.6 ; python_version >= "3.7" and python_version < "4.0" -mccabe==0.7.0 ; python_version >= "3.7" and python_version < "4.0" -mock==4.0.3 ; python_version >= "3.7" and python_version < "4.0" -more-itertools==9.0.0 ; python_version >= "3.7" and python_version < "4.0" -msgpack==1.0.4 ; python_version >= "3.7" and python_version < "4.0" -msrest==0.6.21 ; python_version >= "3.7" and python_version < "4.0" -mypy-extensions==0.4.3 ; python_version >= "3.7" and python_version < "4.0" -mypy==0.982 ; python_version >= "3.7" and python_version < "4.0" -oauth2client==4.1.3 ; python_version >= "3.7" and python_version < "4.0" -oauthlib==3.2.2 ; python_version >= "3.7" and python_version < "4.0" -packaging==22.0 ; python_version >= "3.7" and python_version < "4.0" -paramiko==2.12.0 ; python_version >= "3.7" and python_version < "4.0" -parsedatetime==2.6 ; python_version >= "3.7" and python_version < "4.0" -parso==0.8.3 ; python_version >= "3.7" and python_version < "4.0" -pathlib2==2.3.7.post1 ; python_version >= "3.7" and python_version < "4.0" -pexpect==4.8.0 ; python_version >= "3.7" and python_version < "4.0" -pickleshare==0.7.5 ; python_version >= "3.7" and python_version < "4.0" -pip==22.3.1 ; python_version >= "3.7" and python_version < "4.0" -pkginfo==1.9.2 ; python_version >= "3.7" and python_version < "4.0" -pkgutil-resolve-name==1.3.10 ; python_version >= "3.7" and python_version < "3.9" -platformdirs==2.6.0 ; python_version >= "3.7" and python_version < "4.0" -pluggy==1.0.0 ; python_version >= "3.7" and python_version < "4.0" -ply==3.11 ; python_version >= "3.7" and python_version < "4.0" -poetry-core==1.3.2 ; python_version >= "3.7" and python_version < "4.0" -poetry-plugin-export==1.2.0 ; python_version >= "3.7" and python_version < "4.0" -poetry==1.2.2 ; python_version >= "3.7" and python_version < "4.0" -prompt-toolkit==3.0.36 ; python_version >= "3.7" and python_version < "4.0" -protobuf==4.21.12 ; python_version >= "3.7" and python_version < "4.0" -ptyprocess==0.7.0 ; python_version >= "3.7" and python_version < "4.0" -py==1.11.0 ; python_version >= "3.7" and python_version < "4.0" -pyasn1-modules==0.2.8 ; python_version >= "3.7" and python_version < "4.0" -pyasn1==0.4.8 ; python_version >= "3.7" and python_version < "4.0" -pycparser==2.21 ; python_version >= "3.7" and python_version < "4.0" -pygments==2.13.0 ; python_version >= "3.7" and python_version < "4.0" -pylev==1.4.0 ; python_version >= "3.7" and python_version < "4.0" -pylint==2.13.9 ; python_version >= "3.7" and python_version < "4.0" -pynacl==1.5.0 ; python_version >= "3.7" and python_version < "4.0" -pynsist==2.7 ; python_version >= "3.7" and python_version < "4.0" -pyopenssl==22.1.0 ; python_version >= "3.7" and python_version < "4.0" -pyparsing==3.0.9 ; python_version >= "3.7" and python_version < "4.0" -pyrfc3339==1.1 ; python_version >= "3.7" and python_version < "4.0" -pyrsistent==0.19.2 ; python_version >= "3.7" and python_version < "4.0" -pytest-cov==4.0.0 ; python_version >= "3.7" and python_version < "4.0" -pytest-xdist==3.1.0 ; python_version >= "3.7" and python_version < "4.0" -pytest==7.2.0 ; python_version >= "3.7" and python_version < "4.0" -python-augeas==1.1.0 ; python_version >= "3.7" and python_version < "4.0" -python-dateutil==2.8.2 ; python_version >= "3.7" and python_version < "4.0" -python-digitalocean==1.17.0 ; python_version >= "3.7" and python_version < "4.0" -pytz==2022.6 ; python_version >= "3.7" and python_version < "4.0" -pywin32-ctypes==0.2.0 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "win32" -pywin32==305 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "win32" -pyyaml==5.4.1 ; python_version >= "3.7" and python_version < "4.0" -readme-renderer==37.3 ; python_version >= "3.7" and python_version < "4.0" -requests-download==0.1.2 ; python_version >= "3.7" and python_version < "4.0" -requests-file==1.5.1 ; python_version >= "3.7" and python_version < "4.0" -requests-oauthlib==1.3.1 ; python_version >= "3.7" and python_version < "4.0" -requests-toolbelt==0.9.1 ; python_version >= "3.7" and python_version < "4.0" -requests==2.28.1 ; python_version >= "3.7" and python_version < "4" -rfc3986==2.0.0 ; python_version >= "3.7" and python_version < "4.0" -rich==12.6.0 ; python_version >= "3.7" and python_version < "4.0" -rsa==4.7.2 ; python_version >= "3.7" and python_version < "4" -s3transfer==0.6.0 ; python_version >= "3.7" and python_version < "4.0" -secretstorage==3.3.3 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux" -semantic-version==2.10.0 ; python_version >= "3.7" and python_version < "4.0" -setuptools-rust==1.5.2 ; python_version >= "3.7" and python_version < "4.0" -setuptools==65.6.3 ; python_version >= "3.7" and python_version < "4.0" -shellingham==1.5.0 ; python_version >= "3.7" and python_version < "4.0" -six==1.16.0 ; python_version >= "3.7" and python_version < "4.0" -snowballstemmer==2.2.0 ; python_version >= "3.7" and python_version < "4.0" -soupsieve==2.3.2.post1 ; python_version >= "3.7" and python_version < "4.0" -sphinx-rtd-theme==1.1.1 ; python_version >= "3.7" and python_version < "4.0" -sphinx==5.1.1 ; python_version >= "3.7" and python_version < "4.0" -sphinxcontrib-applehelp==1.0.2 ; python_version >= "3.7" and python_version < "4.0" -sphinxcontrib-devhelp==1.0.2 ; python_version >= "3.7" and python_version < "4.0" -sphinxcontrib-htmlhelp==2.0.0 ; python_version >= "3.7" and python_version < "4.0" -sphinxcontrib-jsmath==1.0.1 ; python_version >= "3.7" and python_version < "4.0" -sphinxcontrib-qthelp==1.0.3 ; python_version >= "3.7" and python_version < "4.0" -sphinxcontrib-serializinghtml==1.1.5 ; python_version >= "3.7" and python_version < "4.0" -tldextract==3.4.0 ; python_version >= "3.7" and python_version < "4.0" -tomli==2.0.1 ; python_version >= "3.7" and python_full_version <= "3.11.0a6" -tomlkit==0.11.6 ; python_version >= "3.7" and python_version < "4.0" -tox==3.27.1 ; python_version >= "3.7" and python_version < "4.0" -traitlets==5.7.1 ; python_version >= "3.7" and python_version < "4.0" -twine==4.0.2 ; python_version >= "3.7" and python_version < "4.0" -typed-ast==1.5.4 ; python_version >= "3.7" and python_version < "3.8" -types-cryptography==3.3.23.2 ; python_version >= "3.7" and python_version < "4.0" -types-mock==4.0.15.2 ; python_version >= "3.7" and python_version < "4.0" -types-pyopenssl==22.1.0.2 ; python_version >= "3.7" and python_version < "4.0" -types-pyrfc3339==1.1.1.1 ; python_version >= "3.7" and python_version < "4.0" -types-python-dateutil==2.8.19.4 ; python_version >= "3.7" and python_version < "4.0" -types-pytz==2022.6.0.1 ; python_version >= "3.7" and python_version < "4.0" -types-requests==2.28.11.5 ; python_version >= "3.7" and python_version < "4.0" -types-setuptools==65.6.0.2 ; python_version >= "3.7" and python_version < "4.0" -types-six==1.16.21.4 ; python_version >= "3.7" and python_version < "4.0" -types-urllib3==1.26.25.4 ; python_version >= "3.7" and python_version < "4.0" -typing-extensions==4.4.0 ; python_version >= "3.7" and python_version < "4.0" -uritemplate==4.1.1 ; python_version >= "3.7" and python_version < "4.0" -urllib3==1.26.13 ; python_version >= "3.7" and python_version < "4.0" -virtualenv==20.17.1 ; python_version >= "3.7" and python_version < "4.0" -wcwidth==0.2.5 ; python_version >= "3.7" and python_version < "4.0" -webencodings==0.5.1 ; python_version >= "3.7" and python_version < "4.0" -wheel==0.38.4 ; python_version >= "3.7" and python_version < "4.0" -wrapt==1.14.1 ; python_version >= "3.7" and python_version < "4.0" -xattr==0.9.9 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "darwin" -yarg==0.1.9 ; python_version >= "3.7" and python_version < "4.0" -zipp==3.11.0 ; python_version >= "3.7" and python_version < "4.0" -zope-component==5.0.1 ; python_version >= "3.7" and python_version < "4.0" -zope-event==4.6 ; python_version >= "3.7" and python_version < "4.0" -zope-hookable==5.4 ; python_version >= "3.7" and python_version < "4.0" -zope-interface==5.5.2 ; python_version >= "3.7" and python_version < "4.0" From 91005a04227b5444c4162de0cac17f4e2f07e205 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 9 Feb 2023 18:45:06 -0800 Subject: [PATCH 29/57] always push to beta --- .azure-pipelines/release.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.azure-pipelines/release.yml b/.azure-pipelines/release.yml index 2374289e3..edef2d1c3 100644 --- a/.azure-pipelines/release.yml +++ b/.azure-pipelines/release.yml @@ -15,11 +15,5 @@ stages: - template: templates/stages/changelog-stage.yml - template: templates/stages/deploy-stage.yml parameters: - ${{ if startsWith(variables['Build.SourceBranchName'], 'v2') }}: - snapReleaseChannel: beta - ${{ elseif startsWith(variables['Build.SourceBranchName'], 'v1') }}: - snapReleaseChannel: candidate - ${{ else }}: - # This should never happen - snapReleaseChannel: somethingInvalid + snapReleaseChannel: beta - template: templates/stages/notify-failure-stage.yml From ca5f13d0e39f069a49861a1a060fed2eac6f6e5f Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 9 Feb 2023 18:55:29 -0800 Subject: [PATCH 30/57] update snapcraft credentials --- .azure-pipelines/templates/jobs/snap-deploy-job.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.azure-pipelines/templates/jobs/snap-deploy-job.yml b/.azure-pipelines/templates/jobs/snap-deploy-job.yml index d1d709cb9..f4bc8eb00 100644 --- a/.azure-pipelines/templates/jobs/snap-deploy-job.yml +++ b/.azure-pipelines/templates/jobs/snap-deploy-job.yml @@ -19,7 +19,7 @@ jobs: # credential file was created by running: # # snapcraft logout - # snapcraft export-login --channels=candidate,beta,edge snapcraft.cfg + # snapcraft export-login --channels=beta,edge snapcraft.cfg # (provide the shared snapcraft credentials when prompted) # # Then the file was added as a secure file in Azure pipelines @@ -30,7 +30,7 @@ jobs: # https://docs.microsoft.com/en-us/azure/devops/pipelines/library/secure-files?view=azure-devops#q-how-do-i-authorize-a-secure-file-for-use-in-a-specific-pipeline. # # This file has a maximum lifetime of one year and the current file will - # expire on 2023-09-06. The file will need to be updated before then to + # expire on 2024-02-10. The file will need to be updated before then to # prevent automated deploys from breaking. # # Revoking these credentials can be done by changing the password of the From c32da71e8abe90bb7ee7418edd3d351290e2fa58 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 9 Feb 2023 18:56:43 -0800 Subject: [PATCH 31/57] fail faster if we try to use candidate --- .azure-pipelines/templates/jobs/snap-deploy-job.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.azure-pipelines/templates/jobs/snap-deploy-job.yml b/.azure-pipelines/templates/jobs/snap-deploy-job.yml index f4bc8eb00..a3c68af36 100644 --- a/.azure-pipelines/templates/jobs/snap-deploy-job.yml +++ b/.azure-pipelines/templates/jobs/snap-deploy-job.yml @@ -12,7 +12,6 @@ parameters: values: - edge - beta - - candidate jobs: # This job relies on credentials used to publish the Certbot snaps. This From 7d4535a836e13b6c806a22301e6d7d645a7af0f1 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 9 Feb 2023 19:35:37 -0800 Subject: [PATCH 32/57] tweak cloudxns condition --- tools/finish_release.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/finish_release.py b/tools/finish_release.py index 8d720bc60..bf6a14d9f 100755 --- a/tools/finish_release.py +++ b/tools/finish_release.py @@ -47,7 +47,7 @@ REPO_ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) # the current version since we no longer build it. PLUGIN_SNAPS = [os.path.basename(path) for path in glob.glob(os.path.join(REPO_ROOT, 'certbot-dns-*')) - if 'cloudxns' not in path] + if not path.endswith('certbot-dns-cloudxns')] # This list contains the name of all Certbot snaps that should be published to # the stable channel. ALL_SNAPS = ['certbot'] + PLUGIN_SNAPS From 1bb09da2705323f4a790657d8f80e4d1db3cf103 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 10 Feb 2023 10:51:20 -0800 Subject: [PATCH 33/57] Update and run isort (#9573) I want to use isort as part of https://github.com/certbot/certbot/issues/9572 because I want to do it programmatically, however, I felt like the config needed to be tweaked a bit due to it not understanding what is and is not our own code. This PR updates the isort config so it recognizes our own modules and runs `isort .` from the root of the repo to update everything. * update isort config * run "isort ." --- .isort.cfg | 1 + acme/acme/challenges.py | 2 +- acme/acme/fields.py | 3 +-- acme/acme/messages.py | 3 +-- acme/tests/challenges_test.py | 5 ++--- acme/tests/client_test.py | 2 +- acme/tests/crypto_util_test.py | 4 ++-- acme/tests/jose_test.py | 3 ++- acme/tests/messages_test.py | 20 +++++++++++++------ acme/tests/standalone_test.py | 4 ++-- acme/tests/test_util.py | 2 +- .../certbot_apache/_internal/augeasparser.py | 5 ++--- .../certbot_apache/_internal/configurator.py | 19 +++++++++--------- .../certbot_apache/_internal/display_ops.py | 3 +-- .../certbot_apache/_internal/entrypoint.py | 3 +-- .../certbot_apache/_internal/http_01.py | 5 ++--- .../certbot_apache/_internal/obj.py | 3 +-- .../_internal/override_centos.py | 5 ++--- .../_internal/override_debian.py | 9 ++++----- .../_internal/override_fedora.py | 5 ++--- .../certbot_apache/_internal/parser.py | 5 ++--- certbot-apache/tests/augeasnode_test.py | 6 ++---- certbot-apache/tests/centos_test.py | 2 +- certbot-apache/tests/configurator_test.py | 6 ++++-- certbot-apache/tests/http_01_test.py | 2 +- certbot-apache/tests/parser_test.py | 2 ++ certbot-apache/tests/util.py | 2 +- .../certbot_tests/assertions.py | 5 +++-- .../certbot_tests/test_main.py | 7 ++++--- .../utils/certbot_call.py | 3 ++- .../certbot_integration_tests/utils/misc.py | 4 ++-- .../utils/pebble_ocsp_server.py | 4 ++-- .../test_main.py | 2 +- .../configurators/apache/common.py | 7 +++---- .../configurators/common.py | 11 +++++----- .../configurators/nginx/common.py | 3 +-- .../certbot_compatibility_test/test_driver.py | 12 +++++------ .../certbot_compatibility_test/util.py | 2 +- certbot-dns-google/tests/dns_google_test.py | 3 +-- .../certbot_nginx/_internal/configurator.py | 12 +++++------ .../certbot_nginx/_internal/display_ops.py | 3 +-- .../certbot_nginx/_internal/http_01.py | 5 ++--- .../certbot_nginx/_internal/parser.py | 6 +++--- certbot-nginx/tests/configurator_test.py | 3 ++- certbot-nginx/tests/obj_test.py | 6 +++--- certbot-nginx/tests/parser_obj_test.py | 6 ++++-- certbot-nginx/tests/parser_test.py | 5 +++-- certbot-nginx/tests/test_util.py | 2 +- certbot/certbot/_internal/client.py | 4 ++-- certbot/certbot/_internal/main.py | 2 +- certbot/certbot/_internal/storage.py | 2 +- certbot/certbot/compat/filesystem.py | 2 +- certbot/certbot/ocsp.py | 1 - certbot/certbot/plugins/common.py | 3 +-- certbot/certbot/plugins/dns_test_common.py | 2 +- certbot/certbot/tests/util.py | 2 +- certbot/tests/account_test.py | 3 +-- certbot/tests/auth_handler_test.py | 2 +- certbot/tests/cert_manager_test.py | 12 +++++++---- certbot/tests/cli_test.py | 1 - certbot/tests/client_test.py | 5 ++--- certbot/tests/compat/filesystem_test.py | 3 ++- certbot/tests/conftest.py | 1 + certbot/tests/crypto_util_test.py | 2 ++ certbot/tests/display/ops_test.py | 3 +-- certbot/tests/eff_test.py | 1 - certbot/tests/helpful_test.py | 4 ++-- certbot/tests/log_test.py | 4 ++-- certbot/tests/main_test.py | 5 ++--- certbot/tests/ocsp_test.py | 1 - certbot/tests/plugins/disco_test.py | 1 - certbot/tests/plugins/storage_test.py | 1 - certbot/tests/plugins/webroot_test.py | 1 + certbot/tests/renewal_test.py | 3 ++- certbot/tests/reverter_test.py | 1 + certbot/tests/util_test.py | 1 + letstest/letstest/multitester.py | 3 +-- letstest/scripts/version.py | 5 ++++- tests/modification-check.py | 1 - tools/finish_release.py | 4 ++-- tools/install_and_test.py | 1 + 81 files changed, 166 insertions(+), 163 deletions(-) diff --git a/.isort.cfg b/.isort.cfg index 6b17b459b..ce2d6c6de 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -4,3 +4,4 @@ force_sort_within_sections=True force_single_line=True order_by_type=False line_length=400 +src_paths=acme/acme,acme/tests,certbot*/certbot*,certbot*/tests diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index 61af415bd..818df9032 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -5,8 +5,8 @@ import functools import hashlib import logging import socket -from typing import cast from typing import Any +from typing import cast from typing import Dict from typing import Mapping from typing import Optional diff --git a/acme/acme/fields.py b/acme/acme/fields.py index d642d10c5..bcd0346d8 100644 --- a/acme/acme/fields.py +++ b/acme/acme/fields.py @@ -1,8 +1,7 @@ """ACME JSON fields.""" import datetime -from typing import Any - import logging +from typing import Any import josepy as jose import pyrfc3339 diff --git a/acme/acme/messages.py b/acme/acme/messages.py index c1af1991a..07a6f4ec5 100644 --- a/acme/acme/messages.py +++ b/acme/acme/messages.py @@ -1,6 +1,6 @@ """ACME protocol messages.""" -import datetime from collections.abc import Hashable +import datetime import json from typing import Any from typing import Dict @@ -21,7 +21,6 @@ from acme import fields from acme import jws from acme import util - ERROR_PREFIX = "urn:ietf:params:acme:error:" ERROR_CODES = { diff --git a/acme/tests/challenges_test.py b/acme/tests/challenges_test.py index 9e31b36c1..1a855788c 100644 --- a/acme/tests/challenges_test.py +++ b/acme/tests/challenges_test.py @@ -1,15 +1,14 @@ """Tests for acme.challenges.""" -import urllib.parse as urllib_parse import unittest from unittest import mock +import urllib.parse as urllib_parse import josepy as jose +from josepy.jwk import JWKEC import OpenSSL import requests -from josepy.jwk import JWKEC from acme import errors - import test_util CERT = test_util.load_comparable_cert('cert.pem') diff --git a/acme/tests/client_test.py b/acme/tests/client_test.py index 093ac519a..06f527e84 100644 --- a/acme/tests/client_test.py +++ b/acme/tests/client_test.py @@ -4,8 +4,8 @@ import copy import datetime import http.client as http_client import json -import unittest from typing import Dict +import unittest from unittest import mock import josepy as jose diff --git a/acme/tests/crypto_util_test.py b/acme/tests/crypto_util_test.py index 0244bf835..81f8fcdce 100644 --- a/acme/tests/crypto_util_test.py +++ b/acme/tests/crypto_util_test.py @@ -1,12 +1,12 @@ """Tests for acme.crypto_util.""" -import itertools import ipaddress +import itertools import socket import socketserver import threading import time -import unittest from typing import List +import unittest import josepy as jose import OpenSSL diff --git a/acme/tests/jose_test.py b/acme/tests/jose_test.py index e008cb6fc..1564e0d38 100644 --- a/acme/tests/jose_test.py +++ b/acme/tests/jose_test.py @@ -21,8 +21,9 @@ class JoseTest(unittest.TestCase): # We use the imports below with eval, but pylint doesn't # understand that. - import acme # pylint: disable=unused-import import josepy # pylint: disable=unused-import + + import acme # pylint: disable=unused-import acme_jose_mod = eval(acme_jose_path) # pylint: disable=eval-used josepy_mod = eval(josepy_path) # pylint: disable=eval-used self.assertIs(acme_jose_mod, josepy_mod) diff --git a/acme/tests/messages_test.py b/acme/tests/messages_test.py index 405e801a2..7c1664ba4 100644 --- a/acme/tests/messages_test.py +++ b/acme/tests/messages_test.py @@ -1,7 +1,7 @@ """Tests for acme.messages.""" +import contextlib from typing import Dict import unittest -import contextlib from unittest import mock import warnings @@ -19,7 +19,10 @@ class ErrorTest(unittest.TestCase): """Tests for acme.messages.Error.""" def setUp(self): - from acme.messages import Error, ERROR_PREFIX, Identifier, IDENTIFIER_FQDN + from acme.messages import Error + from acme.messages import ERROR_PREFIX + from acme.messages import Identifier + from acme.messages import IDENTIFIER_FQDN self.error = Error.with_code('malformed', detail='foo', title='title') self.jobj = { 'detail': 'foo', @@ -63,7 +66,8 @@ class ErrorTest(unittest.TestCase): self.assertIsNone(Error().code) def test_is_acme_error(self): - from acme.messages import is_acme_error, Error + from acme.messages import Error + from acme.messages import is_acme_error self.assertTrue(is_acme_error(self.error)) self.assertFalse(is_acme_error(self.error_custom)) self.assertFalse(is_acme_error(Error())) @@ -71,13 +75,15 @@ class ErrorTest(unittest.TestCase): self.assertFalse(is_acme_error("must pet all the {dogs|rabbits}")) def test_unicode_error(self): - from acme.messages import Error, is_acme_error + from acme.messages import Error + from acme.messages import is_acme_error arabic_error = Error.with_code( 'malformed', detail=u'\u0639\u062f\u0627\u0644\u0629', title='title') self.assertTrue(is_acme_error(arabic_error)) def test_with_code(self): - from acme.messages import Error, is_acme_error + from acme.messages import Error + from acme.messages import is_acme_error self.assertTrue(is_acme_error(Error.with_code('badCSR'))) self.assertRaises(ValueError, Error.with_code, 'not an ACME error code') @@ -247,7 +253,9 @@ class RegistrationTest(unittest.TestCase): )) def test_new_registration_from_data_with_eab(self): - from acme.messages import NewRegistration, ExternalAccountBinding, Directory + from acme.messages import Directory + from acme.messages import ExternalAccountBinding + from acme.messages import NewRegistration key = jose.jwk.JWKRSA(key=KEY.public_key()) kid = "kid-for-testing" hmac_key = "hmac-key-for-testing" diff --git a/acme/tests/standalone_test.py b/acme/tests/standalone_test.py index ad5751fcf..db4e39b5a 100644 --- a/acme/tests/standalone_test.py +++ b/acme/tests/standalone_test.py @@ -3,8 +3,8 @@ import http.client as http_client import socket import socketserver import threading -import unittest from typing import Set +import unittest from unittest import mock import josepy as jose @@ -13,7 +13,6 @@ import requests from acme import challenges from acme import crypto_util from acme import errors - import test_util @@ -190,6 +189,7 @@ class BaseDualNetworkedServersTest(unittest.TestCase): @mock.patch("socket.socket.bind") def test_fail_to_bind(self, mock_bind): from errno import EADDRINUSE + from acme.standalone import BaseDualNetworkedServers mock_bind.side_effect = socket.error(EADDRINUSE, "Fake addr in use error") diff --git a/acme/tests/test_util.py b/acme/tests/test_util.py index efa5a219c..9a5de4b25 100644 --- a/acme/tests/test_util.py +++ b/acme/tests/test_util.py @@ -8,9 +8,9 @@ import os from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization import josepy as jose +from josepy.util import ComparableECKey from OpenSSL import crypto import pkg_resources -from josepy.util import ComparableECKey def load_vector(*names): diff --git a/certbot-apache/certbot_apache/_internal/augeasparser.py b/certbot-apache/certbot_apache/_internal/augeasparser.py index cc57c9cb6..7eca461a3 100644 --- a/certbot-apache/certbot_apache/_internal/augeasparser.py +++ b/certbot-apache/certbot_apache/_internal/augeasparser.py @@ -74,15 +74,14 @@ from typing import Set from typing import Tuple from typing import Union +from certbot import errors +from certbot.compat import os from certbot_apache._internal import apache_util from certbot_apache._internal import assertions from certbot_apache._internal import interfaces from certbot_apache._internal import parser from certbot_apache._internal import parsernode_util as util -from certbot import errors -from certbot.compat import os - class AugeasParserNode(interfaces.ParserNode): """ Augeas implementation of ParserNode interface """ diff --git a/certbot-apache/certbot_apache/_internal/configurator.py b/certbot-apache/certbot_apache/_internal/configurator.py index 41209deb4..37d32f699 100644 --- a/certbot-apache/certbot_apache/_internal/configurator.py +++ b/certbot-apache/certbot_apache/_internal/configurator.py @@ -21,16 +21,6 @@ from typing import Tuple from typing import Type from typing import Union -from certbot_apache._internal import apache_util -from certbot_apache._internal import assertions -from certbot_apache._internal import constants -from certbot_apache._internal import display_ops -from certbot_apache._internal import dualparser -from certbot_apache._internal import http_01 -from certbot_apache._internal import obj -from certbot_apache._internal import parser -from certbot_apache._internal.apacheparser import ApacheBlockNode - from acme import challenges from certbot import achallenges from certbot import errors @@ -42,6 +32,15 @@ from certbot.interfaces import RenewableCert from certbot.plugins import common from certbot.plugins.enhancements import AutoHSTSEnhancement from certbot.plugins.util import path_surgery +from certbot_apache._internal import apache_util +from certbot_apache._internal import assertions +from certbot_apache._internal import constants +from certbot_apache._internal import display_ops +from certbot_apache._internal import dualparser +from certbot_apache._internal import http_01 +from certbot_apache._internal import obj +from certbot_apache._internal import parser +from certbot_apache._internal.apacheparser import ApacheBlockNode try: import apacheconfig diff --git a/certbot-apache/certbot_apache/_internal/display_ops.py b/certbot-apache/certbot_apache/_internal/display_ops.py index b943f988d..251be1da4 100644 --- a/certbot-apache/certbot_apache/_internal/display_ops.py +++ b/certbot-apache/certbot_apache/_internal/display_ops.py @@ -6,11 +6,10 @@ from typing import Optional from typing import Sequence from typing import Tuple -from certbot_apache._internal.obj import VirtualHost - from certbot import errors from certbot.compat import os from certbot.display import util as display_util +from certbot_apache._internal.obj import VirtualHost logger = logging.getLogger(__name__) diff --git a/certbot-apache/certbot_apache/_internal/entrypoint.py b/certbot-apache/certbot_apache/_internal/entrypoint.py index 3f8a00411..c4714b382 100644 --- a/certbot-apache/certbot_apache/_internal/entrypoint.py +++ b/certbot-apache/certbot_apache/_internal/entrypoint.py @@ -2,6 +2,7 @@ from typing import Dict from typing import Type +from certbot import util from certbot_apache._internal import configurator from certbot_apache._internal import override_arch from certbot_apache._internal import override_centos @@ -12,8 +13,6 @@ from certbot_apache._internal import override_gentoo from certbot_apache._internal import override_suse from certbot_apache._internal import override_void -from certbot import util - OVERRIDE_CLASSES: Dict[str, Type[configurator.ApacheConfigurator]] = { "arch": override_arch.ArchConfigurator, "cloudlinux": override_centos.CentOSConfigurator, diff --git a/certbot-apache/certbot_apache/_internal/http_01.py b/certbot-apache/certbot_apache/_internal/http_01.py index e7ca87608..bba7cbaef 100644 --- a/certbot-apache/certbot_apache/_internal/http_01.py +++ b/certbot-apache/certbot_apache/_internal/http_01.py @@ -5,15 +5,14 @@ from typing import List from typing import Set from typing import TYPE_CHECKING -from certbot_apache._internal.obj import VirtualHost -from certbot_apache._internal.parser import get_aug_path - from acme.challenges import KeyAuthorizationChallengeResponse from certbot import errors from certbot.achallenges import KeyAuthorizationAnnotatedChallenge from certbot.compat import filesystem from certbot.compat import os from certbot.plugins import common +from certbot_apache._internal.obj import VirtualHost +from certbot_apache._internal.parser import get_aug_path if TYPE_CHECKING: from certbot_apache._internal.configurator import ApacheConfigurator # pragma: no cover diff --git a/certbot-apache/certbot_apache/_internal/obj.py b/certbot-apache/certbot_apache/_internal/obj.py index b05608699..9a14a60a2 100644 --- a/certbot-apache/certbot_apache/_internal/obj.py +++ b/certbot-apache/certbot_apache/_internal/obj.py @@ -7,12 +7,11 @@ from typing import Pattern from typing import Set from typing import Union +from certbot.plugins import common from certbot_apache._internal.apacheparser import ApacheBlockNode from certbot_apache._internal.augeasparser import AugeasBlockNode from certbot_apache._internal.dualparser import DualBlockNode -from certbot.plugins import common - class Addr(common.Addr): """Represents an Apache address.""" diff --git a/certbot-apache/certbot_apache/_internal/override_centos.py b/certbot-apache/certbot_apache/_internal/override_centos.py index 9883bb1f1..59044769b 100644 --- a/certbot-apache/certbot_apache/_internal/override_centos.py +++ b/certbot-apache/certbot_apache/_internal/override_centos.py @@ -2,14 +2,13 @@ import logging from typing import Any +from certbot import errors +from certbot import util from certbot_apache._internal import apache_util from certbot_apache._internal import configurator from certbot_apache._internal import parser from certbot_apache._internal.configurator import OsOptions -from certbot import errors -from certbot import util - logger = logging.getLogger(__name__) diff --git a/certbot-apache/certbot_apache/_internal/override_debian.py b/certbot-apache/certbot_apache/_internal/override_debian.py index 8c0465538..0d138ee9d 100644 --- a/certbot-apache/certbot_apache/_internal/override_debian.py +++ b/certbot-apache/certbot_apache/_internal/override_debian.py @@ -1,15 +1,14 @@ """ Distribution specific override class for Debian family (Ubuntu/Debian) """ import logging -from certbot_apache._internal import apache_util -from certbot_apache._internal import configurator -from certbot_apache._internal.configurator import OsOptions -from certbot_apache._internal.obj import VirtualHost - from certbot import errors from certbot import util from certbot.compat import filesystem from certbot.compat import os +from certbot_apache._internal import apache_util +from certbot_apache._internal import configurator +from certbot_apache._internal.configurator import OsOptions +from certbot_apache._internal.obj import VirtualHost logger = logging.getLogger(__name__) diff --git a/certbot-apache/certbot_apache/_internal/override_fedora.py b/certbot-apache/certbot_apache/_internal/override_fedora.py index 2e7115df6..a93f103b1 100644 --- a/certbot-apache/certbot_apache/_internal/override_fedora.py +++ b/certbot-apache/certbot_apache/_internal/override_fedora.py @@ -1,14 +1,13 @@ """ Distribution specific override class for Fedora 29+ """ from typing import Any +from certbot import errors +from certbot import util from certbot_apache._internal import apache_util from certbot_apache._internal import configurator from certbot_apache._internal import parser from certbot_apache._internal.configurator import OsOptions -from certbot import errors -from certbot import util - class FedoraConfigurator(configurator.ApacheConfigurator): """Fedora 29+ specific ApacheConfigurator override class""" diff --git a/certbot-apache/certbot_apache/_internal/parser.py b/certbot-apache/certbot_apache/_internal/parser.py index 9805ad781..acfaad762 100644 --- a/certbot-apache/certbot_apache/_internal/parser.py +++ b/certbot-apache/certbot_apache/_internal/parser.py @@ -15,11 +15,10 @@ from typing import Tuple from typing import TYPE_CHECKING from typing import Union -from certbot_apache._internal import apache_util -from certbot_apache._internal import constants - from certbot import errors from certbot.compat import os +from certbot_apache._internal import apache_util +from certbot_apache._internal import constants if TYPE_CHECKING: from certbot_apache._internal.configurator import ApacheConfigurator # pragma: no cover diff --git a/certbot-apache/tests/augeasnode_test.py b/certbot-apache/tests/augeasnode_test.py index 591634d35..01ae35628 100644 --- a/certbot-apache/tests/augeasnode_test.py +++ b/certbot-apache/tests/augeasnode_test.py @@ -1,14 +1,12 @@ """Tests for AugeasParserNode classes""" -from typing import List - import os -import util +from typing import List from unittest import mock from certbot import errors - from certbot_apache._internal import assertions from certbot_apache._internal import augeasparser +import util def _get_augeasnode_mock(filepath): diff --git a/certbot-apache/tests/centos_test.py b/certbot-apache/tests/centos_test.py index 3f8e88467..71cc6df00 100644 --- a/certbot-apache/tests/centos_test.py +++ b/certbot-apache/tests/centos_test.py @@ -5,8 +5,8 @@ from unittest import mock from certbot import errors from certbot.compat import filesystem from certbot.compat import os -from certbot_apache._internal import override_centos from certbot_apache._internal import obj +from certbot_apache._internal import override_centos import util diff --git a/certbot-apache/tests/configurator_test.py b/certbot-apache/tests/configurator_test.py index 0978b302e..f1f9a5e0d 100644 --- a/certbot-apache/tests/configurator_test.py +++ b/certbot-apache/tests/configurator_test.py @@ -86,6 +86,7 @@ class MultipleVhostsTest(util.ApacheTest): def test_add_parser_arguments(self): # pylint: disable=no-self-use from certbot_apache._internal.configurator import ApacheConfigurator + # Weak test.. ApacheConfigurator.add_parser_arguments(mock.MagicMock()) @@ -123,8 +124,8 @@ class MultipleVhostsTest(util.ApacheTest): cls.add_parser_arguments(mock.MagicMock()) def test_all_configurators_defaults_defined(self): - from certbot_apache._internal.entrypoint import OVERRIDE_CLASSES from certbot_apache._internal.configurator import ApacheConfigurator + from certbot_apache._internal.entrypoint import OVERRIDE_CLASSES parameters = set(ApacheConfigurator.OS_DEFAULTS.__dict__.keys()) for cls in OVERRIDE_CLASSES.values(): self.assertIs(parameters.issubset(set(cls.OS_DEFAULTS.__dict__.keys())), True) @@ -1669,9 +1670,10 @@ class InstallSslOptionsConfTest(util.ApacheTest): file has been manually edited by the user, and will refuse to update it. This test ensures that all necessary hashes are present. """ - from certbot_apache._internal.constants import ALL_SSL_OPTIONS_HASHES import pkg_resources + from certbot_apache._internal.constants import ALL_SSL_OPTIONS_HASHES + tls_configs_dir = pkg_resources.resource_filename( "certbot_apache", os.path.join("_internal", "tls_configs")) all_files = [os.path.join(tls_configs_dir, name) for name in os.listdir(tls_configs_dir) diff --git a/certbot-apache/tests/http_01_test.py b/certbot-apache/tests/http_01_test.py index fe5b69b33..6ece4c6be 100644 --- a/certbot-apache/tests/http_01_test.py +++ b/certbot-apache/tests/http_01_test.py @@ -1,7 +1,7 @@ """Test for certbot_apache._internal.http_01.""" -import unittest import errno from typing import List +import unittest from unittest import mock from acme import challenges diff --git a/certbot-apache/tests/parser_test.py b/certbot-apache/tests/parser_test.py index 89633ae47..77b2f34ec 100644 --- a/certbot-apache/tests/parser_test.py +++ b/certbot-apache/tests/parser_test.py @@ -128,6 +128,7 @@ class BasicParserTest(util.ParserTest): """ from certbot_apache._internal.parser import get_aug_path + # This makes sure that find_dir will work self.parser.modules["mod_ssl.c"] = "/fake/path" @@ -142,6 +143,7 @@ class BasicParserTest(util.ParserTest): def test_add_dir_to_ifmodssl_multiple(self): from certbot_apache._internal.parser import get_aug_path + # This makes sure that find_dir will work self.parser.modules["mod_ssl.c"] = "/fake/path" diff --git a/certbot-apache/tests/util.py b/certbot-apache/tests/util.py index 7cea90f25..57c374f07 100644 --- a/certbot-apache/tests/util.py +++ b/certbot-apache/tests/util.py @@ -1,10 +1,10 @@ """Common utilities for certbot_apache.""" import shutil import unittest +from unittest import mock import augeas import josepy as jose -from unittest import mock from certbot.compat import os from certbot.plugins import common diff --git a/certbot-ci/certbot_integration_tests/certbot_tests/assertions.py b/certbot-ci/certbot_integration_tests/certbot_tests/assertions.py index 7731f27d7..62d99fb0e 100644 --- a/certbot-ci/certbot_integration_tests/certbot_tests/assertions.py +++ b/certbot-ci/certbot_integration_tests/certbot_tests/assertions.py @@ -5,7 +5,8 @@ from typing import Optional from typing import Type from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateKey, EllipticCurve +from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurve +from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateKey from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey from cryptography.hazmat.primitives.serialization import load_pem_private_key @@ -13,8 +14,8 @@ try: import grp POSIX_MODE = True except ImportError: - import win32security import ntsecuritycon + import win32security POSIX_MODE = False EVERYBODY_SID = 'S-1-1-0' diff --git a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py index 66aa1aa23..53f09b341 100644 --- a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py +++ b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py @@ -6,8 +6,8 @@ import re import shutil import subprocess import time -from typing import Iterable from typing import Generator +from typing import Iterable from typing import Tuple from typing import Type @@ -18,7 +18,6 @@ from cryptography.hazmat.primitives.asymmetric.ec import SECP521R1 from cryptography.x509 import NameOID import pytest -from certbot_integration_tests.certbot_tests.context import IntegrationTestsContext from certbot_integration_tests.certbot_tests.assertions import assert_cert_count_for_lineage from certbot_integration_tests.certbot_tests.assertions import assert_elliptic_key from certbot_integration_tests.certbot_tests.assertions import assert_equals_group_owner @@ -31,6 +30,7 @@ from certbot_integration_tests.certbot_tests.assertions import assert_saved_rene from certbot_integration_tests.certbot_tests.assertions import assert_world_no_permissions from certbot_integration_tests.certbot_tests.assertions import assert_world_read_permissions from certbot_integration_tests.certbot_tests.assertions import EVERYBODY_SID +from certbot_integration_tests.certbot_tests.context import IntegrationTestsContext from certbot_integration_tests.utils import misc @@ -248,8 +248,9 @@ def test_renew_files_propagate_permissions(context: IntegrationTestsContext) -> if os.name != 'nt': os.chmod(privkey1, 0o444) else: - import win32security # pylint: disable=import-error import ntsecuritycon # pylint: disable=import-error + import win32security # pylint: disable=import-error + # Get the current DACL of the private key security = win32security.GetFileSecurity(privkey1, win32security.DACL_SECURITY_INFORMATION) dacl = security.GetSecurityDescriptorDacl() diff --git a/certbot-ci/certbot_integration_tests/utils/certbot_call.py b/certbot-ci/certbot_integration_tests/utils/certbot_call.py index 429cf413e..bcec38be2 100755 --- a/certbot-ci/certbot_integration_tests/utils/certbot_call.py +++ b/certbot-ci/certbot_integration_tests/utils/certbot_call.py @@ -2,7 +2,6 @@ """Module to call certbot in test mode""" import os -import pkg_resources import subprocess import sys from typing import Dict @@ -10,6 +9,8 @@ from typing import List from typing import Mapping from typing import Tuple +import pkg_resources + import certbot_integration_tests # pylint: disable=wildcard-import,unused-wildcard-import from certbot_integration_tests.utils.constants import * diff --git a/certbot-ci/certbot_integration_tests/utils/misc.py b/certbot-ci/certbot_integration_tests/utils/misc.py index 9d6317d87..558b96d40 100644 --- a/certbot-ci/certbot_integration_tests/utils/misc.py +++ b/certbot-ci/certbot_integration_tests/utils/misc.py @@ -15,20 +15,20 @@ import sys import tempfile import threading import time -import warnings from typing import Generator from typing import Iterable from typing import List from typing import Optional from typing import Tuple +import warnings from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives.serialization import Encoding from cryptography.hazmat.primitives.serialization import NoEncryption from cryptography.hazmat.primitives.serialization import PrivateFormat -from cryptography.x509 import load_pem_x509_certificate from cryptography.x509 import Certificate +from cryptography.x509 import load_pem_x509_certificate from OpenSSL import crypto import pkg_resources import requests diff --git a/certbot-ci/certbot_integration_tests/utils/pebble_ocsp_server.py b/certbot-ci/certbot_integration_tests/utils/pebble_ocsp_server.py index d0f7a2123..1749b03da 100755 --- a/certbot-ci/certbot_integration_tests/utils/pebble_ocsp_server.py +++ b/certbot-ci/certbot_integration_tests/utils/pebble_ocsp_server.py @@ -6,6 +6,8 @@ to serve a mock OCSP responder during integration tests against Pebble. import datetime import http.server as BaseHTTPServer import re +from typing import cast +from typing import Union from cryptography import x509 from cryptography.hazmat.backends import default_backend @@ -16,8 +18,6 @@ from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey from cryptography.x509 import ocsp from dateutil import parser import requests -from typing import cast -from typing import Union from certbot_integration_tests.utils.constants import MOCK_OCSP_SERVER_PORT from certbot_integration_tests.utils.constants import PEBBLE_MANAGEMENT_URL diff --git a/certbot-ci/windows_installer_integration_tests/test_main.py b/certbot-ci/windows_installer_integration_tests/test_main.py index ad1622bde..be6447a96 100644 --- a/certbot-ci/windows_installer_integration_tests/test_main.py +++ b/certbot-ci/windows_installer_integration_tests/test_main.py @@ -3,8 +3,8 @@ import os import re import subprocess import time -import unittest from typing import Any +import unittest import pytest diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py index fda51f3a0..ca8a02b18 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/apache/common.py @@ -7,15 +7,14 @@ from typing import Set from typing import Tuple from unittest import mock +from certbot import configuration +from certbot import errors as le_errors +from certbot import util as certbot_util from certbot_apache._internal import entrypoint from certbot_compatibility_test import errors from certbot_compatibility_test import util from certbot_compatibility_test.configurators import common as configurators_common -from certbot import configuration -from certbot import errors as le_errors -from certbot import util as certbot_util - class Proxy(configurators_common.Proxy): """A common base for Apache test configurators""" diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py index a115e8419..44a1cec01 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/common.py @@ -8,21 +8,20 @@ import tempfile from typing import Iterable from typing import List from typing import Optional -from typing import Union from typing import overload from typing import Set from typing import Tuple from typing import Type - -from certbot_compatibility_test import errors -from certbot_compatibility_test import interfaces -from certbot_compatibility_test import util +from typing import Union from acme import challenges from acme.challenges import Challenge from certbot._internal import constants -from certbot.plugins import common from certbot.achallenges import AnnotatedChallenge +from certbot.plugins import common +from certbot_compatibility_test import errors +from certbot_compatibility_test import interfaces +from certbot_compatibility_test import util logger = logging.getLogger(__name__) diff --git a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py index 1282923bf..6f2b9c1ae 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py +++ b/certbot-compatibility-test/certbot_compatibility_test/configurators/nginx/common.py @@ -5,14 +5,13 @@ import subprocess from typing import Set from typing import Tuple +from certbot import configuration from certbot_compatibility_test import errors from certbot_compatibility_test import util from certbot_compatibility_test.configurators import common as configurators_common from certbot_nginx._internal import configurator from certbot_nginx._internal import constants -from certbot import configuration - class Proxy(configurators_common.Proxy): """A common base for Nginx test configurators""" diff --git a/certbot-compatibility-test/certbot_compatibility_test/test_driver.py b/certbot-compatibility-test/certbot_compatibility_test/test_driver.py index 6a29e74f5..2baa207f6 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/test_driver.py +++ b/certbot-compatibility-test/certbot_compatibility_test/test_driver.py @@ -18,12 +18,6 @@ from typing import Optional from typing import Tuple from typing import Type -from certbot_compatibility_test import errors -from certbot_compatibility_test import util -from certbot_compatibility_test import validator -from certbot_compatibility_test.configurators import common -from certbot_compatibility_test.configurators.apache import common as a_common -from certbot_compatibility_test.configurators.nginx import common as n_common from OpenSSL import crypto from urllib3.util import connection @@ -34,6 +28,12 @@ from certbot import achallenges from certbot import errors as le_errors from certbot._internal.display import obj as display_obj from certbot.tests import acme_util +from certbot_compatibility_test import errors +from certbot_compatibility_test import util +from certbot_compatibility_test import validator +from certbot_compatibility_test.configurators import common +from certbot_compatibility_test.configurators.apache import common as a_common +from certbot_compatibility_test.configurators.nginx import common as n_common DESCRIPTION = """ Tests Certbot plugins against different server configurations. It is diff --git a/certbot-compatibility-test/certbot_compatibility_test/util.py b/certbot-compatibility-test/certbot_compatibility_test/util.py index 2a69d3835..4fe2e417d 100644 --- a/certbot-compatibility-test/certbot_compatibility_test/util.py +++ b/certbot-compatibility-test/certbot_compatibility_test/util.py @@ -6,11 +6,11 @@ import re import shutil import tarfile -from certbot_compatibility_test import errors import josepy as jose from certbot._internal import constants from certbot.tests import util as test_util +from certbot_compatibility_test import errors _KEY_BASE = "rsa2048_key.pem" KEY_PATH = test_util.vector_path(_KEY_BASE) diff --git a/certbot-dns-google/tests/dns_google_test.py b/certbot-dns-google/tests/dns_google_test.py index 27e8b1a65..1d27a39a8 100644 --- a/certbot-dns-google/tests/dns_google_test.py +++ b/certbot-dns-google/tests/dns_google_test.py @@ -1,14 +1,13 @@ """Tests for certbot_dns_google._internal.dns_google.""" import unittest +from unittest import mock from googleapiclient import discovery from googleapiclient.errors import Error from googleapiclient.http import HttpMock from httplib2 import ServerNotFoundError -from unittest import mock - from certbot import errors from certbot.compat import os from certbot.errors import PluginError diff --git a/certbot-nginx/certbot_nginx/_internal/configurator.py b/certbot-nginx/certbot_nginx/_internal/configurator.py index 07243df2b..12c6893f9 100644 --- a/certbot-nginx/certbot_nginx/_internal/configurator.py +++ b/certbot-nginx/certbot_nginx/_internal/configurator.py @@ -20,12 +20,6 @@ from typing import Tuple from typing import Type from typing import Union -from certbot_nginx._internal import constants -from certbot_nginx._internal import display_ops -from certbot_nginx._internal import http_01 -from certbot_nginx._internal import nginxparser -from certbot_nginx._internal import obj -from certbot_nginx._internal import parser import OpenSSL import pkg_resources @@ -38,6 +32,12 @@ from certbot import util from certbot.compat import os from certbot.display import util as display_util from certbot.plugins import common +from certbot_nginx._internal import constants +from certbot_nginx._internal import display_ops +from certbot_nginx._internal import http_01 +from certbot_nginx._internal import nginxparser +from certbot_nginx._internal import obj +from certbot_nginx._internal import parser NAME_RANK = 0 START_WILDCARD_RANK = 1 diff --git a/certbot-nginx/certbot_nginx/_internal/display_ops.py b/certbot-nginx/certbot_nginx/_internal/display_ops.py index 89483c94a..3a0fa67ff 100644 --- a/certbot-nginx/certbot_nginx/_internal/display_ops.py +++ b/certbot-nginx/certbot_nginx/_internal/display_ops.py @@ -4,9 +4,8 @@ from typing import Iterable from typing import List from typing import Optional -from certbot_nginx._internal.obj import VirtualHost - from certbot.display import util as display_util +from certbot_nginx._internal.obj import VirtualHost logger = logging.getLogger(__name__) diff --git a/certbot-nginx/certbot_nginx/_internal/http_01.py b/certbot-nginx/certbot_nginx/_internal/http_01.py index 9b086d429..8a6afb0ea 100644 --- a/certbot-nginx/certbot_nginx/_internal/http_01.py +++ b/certbot-nginx/certbot_nginx/_internal/http_01.py @@ -7,15 +7,14 @@ from typing import List from typing import Optional from typing import TYPE_CHECKING -from certbot_nginx._internal import nginxparser -from certbot_nginx._internal.obj import Addr - from acme import challenges from acme.challenges import KeyAuthorizationChallengeResponse from certbot import errors from certbot.achallenges import KeyAuthorizationAnnotatedChallenge from certbot.compat import os from certbot.plugins import common +from certbot_nginx._internal import nginxparser +from certbot_nginx._internal.obj import Addr if TYPE_CHECKING: from certbot_nginx._internal.configurator import NginxConfigurator diff --git a/certbot-nginx/certbot_nginx/_internal/parser.py b/certbot-nginx/certbot_nginx/_internal/parser.py index bc1643426..d5a00f103 100644 --- a/certbot-nginx/certbot_nginx/_internal/parser.py +++ b/certbot-nginx/certbot_nginx/_internal/parser.py @@ -18,13 +18,13 @@ from typing import Set from typing import Tuple from typing import Union -from certbot_nginx._internal import nginxparser -from certbot_nginx._internal import obj -from certbot_nginx._internal.nginxparser import UnspacedList import pyparsing from certbot import errors from certbot.compat import os +from certbot_nginx._internal import nginxparser +from certbot_nginx._internal import obj +from certbot_nginx._internal.nginxparser import UnspacedList logger = logging.getLogger(__name__) diff --git a/certbot-nginx/tests/configurator_test.py b/certbot-nginx/tests/configurator_test.py index 916dfe3f5..12dc61a38 100644 --- a/certbot-nginx/tests/configurator_test.py +++ b/certbot-nginx/tests/configurator_test.py @@ -1064,8 +1064,9 @@ class InstallSslOptionsConfTest(util.NginxTest): file has been manually edited by the user, and will refuse to update it. This test ensures that all necessary hashes are present. """ - from certbot_nginx._internal.constants import ALL_SSL_OPTIONS_HASHES import pkg_resources + + from certbot_nginx._internal.constants import ALL_SSL_OPTIONS_HASHES all_files = [ pkg_resources.resource_filename("certbot_nginx", os.path.join("_internal", "tls_configs", x)) diff --git a/certbot-nginx/tests/obj_test.py b/certbot-nginx/tests/obj_test.py index de82e5682..67ca40f1b 100644 --- a/certbot-nginx/tests/obj_test.py +++ b/certbot-nginx/tests/obj_test.py @@ -109,8 +109,8 @@ class AddrTest(unittest.TestCase): class VirtualHostTest(unittest.TestCase): """Test the VirtualHost class.""" def setUp(self): - from certbot_nginx._internal.obj import VirtualHost from certbot_nginx._internal.obj import Addr + from certbot_nginx._internal.obj import VirtualHost raw1 = [ ['listen', '69.50.225.155:9000'], [['if', '($scheme', '!=', '"https") '], @@ -183,9 +183,9 @@ class VirtualHostTest(unittest.TestCase): self.assertIs(self.vhost1.has_header('Bogus-Header'), False) def test_contains_list(self): - from certbot_nginx._internal.obj import VirtualHost - from certbot_nginx._internal.obj import Addr from certbot_nginx._internal.configurator import _test_block_from_block + from certbot_nginx._internal.obj import Addr + from certbot_nginx._internal.obj import VirtualHost test_block = [ ['\n ', 'return', ' ', '301', ' ', 'https://$host$request_uri'], ['\n'] diff --git a/certbot-nginx/tests/parser_obj_test.py b/certbot-nginx/tests/parser_obj_test.py index 60ff1c975..c2243f5be 100644 --- a/certbot-nginx/tests/parser_obj_test.py +++ b/certbot-nginx/tests/parser_obj_test.py @@ -26,7 +26,8 @@ class CommentHelpersTest(unittest.TestCase): parse_raw(['not', 'even', 'a', 'comment']))) def test_certbot_comment(self): - from certbot_nginx._internal.parser_obj import _certbot_comment, _is_certbot_comment + from certbot_nginx._internal.parser_obj import _certbot_comment + from certbot_nginx._internal.parser_obj import _is_certbot_comment comment = _certbot_comment(None) self.assertTrue(_is_certbot_comment(comment)) self.assertEqual(comment.dump(), COMMENT_BLOCK) @@ -156,7 +157,8 @@ class BlockTest(unittest.TestCase): def test_iterate_match(self): # can match on contents while expanded - from certbot_nginx._internal.parser_obj import Block, Sentence + from certbot_nginx._internal.parser_obj import Block + from certbot_nginx._internal.parser_obj import Sentence expected = [['thing', '1'], ['thing', '2']] for i, elem in enumerate(self.bloc.iterate(expanded=True, match=lambda x: isinstance(x, Sentence) and 'thing' in x.words)): diff --git a/certbot-nginx/tests/parser_test.py b/certbot-nginx/tests/parser_test.py index 93a8dcedc..4aaa00ea0 100644 --- a/certbot-nginx/tests/parser_test.py +++ b/certbot-nginx/tests/parser_test.py @@ -2,8 +2,8 @@ import glob import re import shutil -import unittest from typing import List +import unittest from unittest import mock from certbot import errors @@ -371,7 +371,8 @@ class NginxParserTest(util.NginxTest): ["\n", "a", " ", "b", "\n"], ["c", " ", "d"], ["\n", "e", " ", "f"]]) - from certbot_nginx._internal.parser import comment_directive, COMMENT_BLOCK + from certbot_nginx._internal.parser import COMMENT_BLOCK + from certbot_nginx._internal.parser import comment_directive comment_directive(block, 1) comment_directive(block, 0) self.assertEqual(block.spaced, [ diff --git a/certbot-nginx/tests/test_util.py b/certbot-nginx/tests/test_util.py index 1ac649318..d38c515b4 100644 --- a/certbot-nginx/tests/test_util.py +++ b/certbot-nginx/tests/test_util.py @@ -2,9 +2,9 @@ import copy import shutil import tempfile +from unittest import mock import josepy as jose -from unittest import mock import pkg_resources from certbot import util diff --git a/certbot/certbot/_internal/client.py b/certbot/certbot/_internal/client.py index 1fe1df5ec..59f5f8a4e 100644 --- a/certbot/certbot/_internal/client.py +++ b/certbot/certbot/_internal/client.py @@ -2,9 +2,9 @@ import datetime import logging import platform -from typing import cast from typing import Any from typing import Callable +from typing import cast from typing import Dict from typing import IO from typing import List @@ -14,11 +14,11 @@ from typing import Tuple from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric.rsa import generate_private_key import josepy as jose -import OpenSSL from josepy import ES256 from josepy import ES384 from josepy import ES512 from josepy import RS256 +import OpenSSL from acme import client as acme_client from acme import crypto_util as acme_crypto_util diff --git a/certbot/certbot/_internal/main.py b/certbot/certbot/_internal/main.py index 78e6347f9..a8950a151 100644 --- a/certbot/certbot/_internal/main.py +++ b/certbot/certbot/_internal/main.py @@ -1,8 +1,8 @@ """Certbot main entry point.""" # pylint: disable=too-many-lines -import copy from contextlib import contextmanager +import copy import functools import logging.handlers import sys diff --git a/certbot/certbot/_internal/storage.py b/certbot/certbot/_internal/storage.py index cb6d2ef16..086d3882f 100644 --- a/certbot/certbot/_internal/storage.py +++ b/certbot/certbot/_internal/storage.py @@ -18,8 +18,8 @@ from typing import Union import configobj from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateKey +from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey from cryptography.hazmat.primitives.serialization import load_pem_private_key import parsedatetime import pkg_resources diff --git a/certbot/certbot/compat/filesystem.py b/certbot/certbot/compat/filesystem.py index 1bf89a733..b975f95b5 100644 --- a/certbot/certbot/compat/filesystem.py +++ b/certbot/certbot/compat/filesystem.py @@ -8,8 +8,8 @@ import stat import sys from typing import Any from typing import Dict -from typing import List from typing import Generator +from typing import List from typing import Optional try: diff --git a/certbot/certbot/ocsp.py b/certbot/certbot/ocsp.py index 0278adef7..8f558eb7b 100644 --- a/certbot/certbot/ocsp.py +++ b/certbot/certbot/ocsp.py @@ -24,7 +24,6 @@ from certbot import util from certbot.compat.os import getenv from certbot.interfaces import RenewableCert - logger = logging.getLogger(__name__) diff --git a/certbot/certbot/plugins/common.py b/certbot/certbot/plugins/common.py index 1acee2dfc..a6086acad 100644 --- a/certbot/certbot/plugins/common.py +++ b/certbot/certbot/plugins/common.py @@ -19,12 +19,11 @@ from typing import TypeVar import pkg_resources from acme import challenges - from certbot import achallenges from certbot import configuration from certbot import crypto_util -from certbot import interfaces from certbot import errors +from certbot import interfaces from certbot import reverter from certbot._internal import constants from certbot.compat import filesystem diff --git a/certbot/certbot/plugins/dns_test_common.py b/certbot/certbot/plugins/dns_test_common.py index 65c9cc2c8..cb89cd4d9 100644 --- a/certbot/certbot/plugins/dns_test_common.py +++ b/certbot/certbot/plugins/dns_test_common.py @@ -2,10 +2,10 @@ from typing import Any from typing import Mapping from typing import TYPE_CHECKING +from unittest import mock import configobj import josepy as jose -from unittest import mock from acme import challenges from certbot import achallenges diff --git a/certbot/certbot/tests/util.py b/certbot/certbot/tests/util.py index c7bbbb422..5db26c4cd 100644 --- a/certbot/certbot/tests/util.py +++ b/certbot/certbot/tests/util.py @@ -9,12 +9,12 @@ import sys import tempfile from typing import Any from typing import Callable -from typing import Union from typing import cast from typing import IO from typing import Iterable from typing import List from typing import Optional +from typing import Union import unittest from unittest import mock diff --git a/certbot/tests/account_test.py b/certbot/tests/account_test.py index 3daac6498..d60da44c1 100644 --- a/certbot/tests/account_test.py +++ b/certbot/tests/account_test.py @@ -2,9 +2,9 @@ import datetime import json import unittest +from unittest import mock import josepy as jose -from unittest import mock import pytz from acme import messages @@ -14,7 +14,6 @@ from certbot.compat import misc from certbot.compat import os import certbot.tests.util as test_util - KEY = jose.JWKRSA.load(test_util.load_vector("rsa512_key.pem")) diff --git a/certbot/tests/auth_handler_test.py b/certbot/tests/auth_handler_test.py index 548356897..0af351c80 100644 --- a/certbot/tests/auth_handler_test.py +++ b/certbot/tests/auth_handler_test.py @@ -2,9 +2,9 @@ import datetime import logging import unittest +from unittest import mock from josepy import b64encode -from unittest import mock from acme import challenges from acme import client as acme_client diff --git a/certbot/tests/cert_manager_test.py b/certbot/tests/cert_manager_test.py index 157d45b55..08f733bbe 100644 --- a/certbot/tests/cert_manager_test.py +++ b/certbot/tests/cert_manager_test.py @@ -5,11 +5,12 @@ import re import shutil import tempfile import unittest - -import configobj from unittest import mock -from certbot import errors, configuration +import configobj + +from certbot import configuration +from certbot import errors from certbot._internal.storage import ALL_FOUR from certbot.compat import filesystem from certbot.compat import os @@ -247,9 +248,11 @@ class CertificatesTest(BaseCertManagerTest): def test_report_human_readable(self, mock_revoked, mock_serial): mock_revoked.return_value = None mock_serial.return_value = 1234567890 - from certbot._internal import cert_manager import datetime + import pytz + + from certbot._internal import cert_manager expiry = pytz.UTC.fromutc(datetime.datetime.utcnow()) cert = mock.MagicMock(lineagename="nameone") @@ -327,6 +330,7 @@ class SearchLineagesTest(BaseCertManagerTest): mock_renewal_conf_files.return_value = ["badfile"] mock_renewable_cert.side_effect = errors.CertStorageError from certbot._internal import cert_manager + # pylint: disable=protected-access self.assertEqual(cert_manager._search_lineages(self.config, lambda x: x, "check"), "check") self.assertTrue(mock_make_or_verify_dir.called) diff --git a/certbot/tests/cli_test.py b/certbot/tests/cli_test.py index 54abe2594..0b2108b73 100644 --- a/certbot/tests/cli_test.py +++ b/certbot/tests/cli_test.py @@ -17,7 +17,6 @@ from certbot.compat import os import certbot.tests.util as test_util from certbot.tests.util import TempDirTestCase - PLUGINS = disco.PluginsRegistry.find_all() diff --git a/certbot/tests/client_test.py b/certbot/tests/client_test.py index cb16890d3..7b29d26ca 100644 --- a/certbot/tests/client_test.py +++ b/certbot/tests/client_test.py @@ -1,6 +1,6 @@ """Tests for certbot._internal.client.""" -import datetime import contextlib +import datetime import platform import shutil import tempfile @@ -12,13 +12,12 @@ from josepy import interfaces from certbot import errors from certbot import util -from certbot._internal.display import obj as display_obj from certbot._internal import account from certbot._internal import constants +from certbot._internal.display import obj as display_obj from certbot.compat import os import certbot.tests.util as test_util - KEY = test_util.load_vector("rsa512_key.pem") CSR_SAN = test_util.load_vector("csr-san_512.pem") diff --git a/certbot/tests/compat/filesystem_test.py b/certbot/tests/compat/filesystem_test.py index e94068d4e..fd4cb9cde 100644 --- a/certbot/tests/compat/filesystem_test.py +++ b/certbot/tests/compat/filesystem_test.py @@ -12,9 +12,9 @@ import certbot.tests.util as test_util from certbot.tests.util import TempDirTestCase try: + import ntsecuritycon import win32api import win32security - import ntsecuritycon POSIX_MODE = False except ImportError: POSIX_MODE = True @@ -471,6 +471,7 @@ class CheckPermissionsTest(test_util.TempDirTestCase): self.assertIs(filesystem.check_owner(self.probe_path), True) import os as std_os # pylint: disable=os-module-forbidden + # See related inline comment in certbot.compat.filesystem.check_owner method # that explains why MyPy/PyLint check disable is needed here. uid = std_os.getuid() diff --git a/certbot/tests/conftest.py b/certbot/tests/conftest.py index 191e07b55..64ae64983 100644 --- a/certbot/tests/conftest.py +++ b/certbot/tests/conftest.py @@ -2,6 +2,7 @@ import pytest from certbot._internal import cli + @pytest.fixture(autouse=True) def reset_cli_global(): cli.set_by_cli.detector = None diff --git a/certbot/tests/crypto_util_test.py b/certbot/tests/crypto_util_test.py index 3031cf531..46dc86436 100644 --- a/certbot/tests/crypto_util_test.py +++ b/certbot/tests/crypto_util_test.py @@ -164,6 +164,7 @@ class MakeKeyTest(unittest.TestCase): def test_rsa(self): # pylint: disable=no-self-use # RSA Key Type Test from certbot.crypto_util import make_key + # Do not test larger keys as it takes too long. OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, make_key(1024)) @@ -180,6 +181,7 @@ class MakeKeyTest(unittest.TestCase): def test_bad_key_sizes(self): from certbot.crypto_util import make_key + # Try a bad key size for RSA and ECDSA with self.assertRaises(errors.Error) as e: make_key(bits=512, key_type='rsa') diff --git a/certbot/tests/display/ops_test.py b/certbot/tests/display/ops_test.py index 1235190a7..69c7440be 100644 --- a/certbot/tests/display/ops_test.py +++ b/certbot/tests/display/ops_test.py @@ -8,15 +8,14 @@ import josepy as jose from acme import messages from certbot import errors -from certbot._internal.display import obj as display_obj from certbot._internal import account +from certbot._internal.display import obj as display_obj from certbot.compat import filesystem from certbot.compat import os from certbot.display import ops from certbot.display import util as display_util import certbot.tests.util as test_util - KEY = jose.JWKRSA.load(test_util.load_vector("rsa512_key.pem")) diff --git a/certbot/tests/eff_test.py b/certbot/tests/eff_test.py index 6a8ac2c61..a87ca2204 100644 --- a/certbot/tests/eff_test.py +++ b/certbot/tests/eff_test.py @@ -12,7 +12,6 @@ from certbot._internal import account from certbot._internal import constants import certbot.tests.util as test_util - _KEY = josepy.JWKRSA.load(test_util.load_vector("rsa512_key.pem")) diff --git a/certbot/tests/helpful_test.py b/certbot/tests/helpful_test.py index c67211a43..2965f582a 100644 --- a/certbot/tests/helpful_test.py +++ b/certbot/tests/helpful_test.py @@ -3,9 +3,9 @@ import unittest from unittest import mock from certbot import errors -from certbot._internal.cli import HelpfulArgumentParser -from certbot._internal.cli import _DomainsAction from certbot._internal import constants +from certbot._internal.cli import _DomainsAction +from certbot._internal.cli import HelpfulArgumentParser class TestScanningFlags(unittest.TestCase): diff --git a/certbot/tests/log_test.py b/certbot/tests/log_test.py index 855582591..bee33261c 100644 --- a/certbot/tests/log_test.py +++ b/certbot/tests/log_test.py @@ -17,7 +17,6 @@ from certbot.compat import os from certbot.tests import util as test_util - class PreArgParseSetupTest(unittest.TestCase): """Tests for certbot._internal.log.pre_arg_parse_setup.""" @@ -79,7 +78,8 @@ class PostArgParseSetupTest(test_util.ConfigTestCase): from certbot._internal.log import ColoredStreamHandler self.stream_handler = ColoredStreamHandler(io.StringIO()) - from certbot._internal.log import MemoryHandler, TempHandler + from certbot._internal.log import MemoryHandler + from certbot._internal.log import TempHandler self.temp_handler = TempHandler() self.temp_path = self.temp_handler.path self.memory_handler = MemoryHandler(self.temp_handler) diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index 0eae761a2..0b24ff30d 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -19,7 +19,8 @@ import josepy as jose import pytz from acme.messages import Error as acme_error -from certbot import crypto_util, configuration +from certbot import configuration +from certbot import crypto_util from certbot import errors from certbot import interfaces from certbot import util @@ -36,8 +37,6 @@ from certbot.compat import os from certbot.plugins import enhancements import certbot.tests.util as test_util - - CERT_PATH = test_util.vector_path('cert_512.pem') CERT = test_util.vector_path('cert_512.pem') CSR = test_util.vector_path('csr_512.der') diff --git a/certbot/tests/ocsp_test.py b/certbot/tests/ocsp_test.py index 802787e02..ebb98c343 100644 --- a/certbot/tests/ocsp_test.py +++ b/certbot/tests/ocsp_test.py @@ -17,7 +17,6 @@ import pytz from certbot import errors from certbot.tests import util as test_util - out = """Missing = in header key=value ocsp: Use -help for summary. """ diff --git a/certbot/tests/plugins/disco_test.py b/certbot/tests/plugins/disco_test.py index cb6e4b53e..dfd9d0c7b 100644 --- a/certbot/tests/plugins/disco_test.py +++ b/certbot/tests/plugins/disco_test.py @@ -13,7 +13,6 @@ from certbot._internal.plugins import null from certbot._internal.plugins import standalone from certbot._internal.plugins import webroot - EP_SA = pkg_resources.EntryPoint( "sa", "certbot._internal.plugins.standalone", attrs=("Authenticator",), diff --git a/certbot/tests/plugins/storage_test.py b/certbot/tests/plugins/storage_test.py index a63ef7795..82b0aff65 100644 --- a/certbot/tests/plugins/storage_test.py +++ b/certbot/tests/plugins/storage_test.py @@ -12,7 +12,6 @@ from certbot.compat import os from certbot.tests import util as test_util - class PluginStorageTest(test_util.ConfigTestCase): """Test for certbot.plugins.storage.PluginStorage""" diff --git a/certbot/tests/plugins/webroot_test.py b/certbot/tests/plugins/webroot_test.py index d5ccc4b4f..4bc198074 100644 --- a/certbot/tests/plugins/webroot_test.py +++ b/certbot/tests/plugins/webroot_test.py @@ -32,6 +32,7 @@ class AuthenticatorTest(unittest.TestCase): def setUp(self): from certbot._internal.plugins.webroot import Authenticator + # On Linux directories created by tempfile.mkdtemp inherit their permissions from their # parent directory. So the actual permissions are inconsistent over various tests env. # To circumvent this, a dedicated sub-workspace is created under the workspace, using diff --git a/certbot/tests/renewal_test.py b/certbot/tests/renewal_test.py index 3cb4ac056..4d337830e 100644 --- a/certbot/tests/renewal_test.py +++ b/certbot/tests/renewal_test.py @@ -4,7 +4,8 @@ import unittest from unittest import mock from acme import challenges -from certbot import errors, configuration +from certbot import configuration +from certbot import errors from certbot._internal import storage import certbot.tests.util as test_util diff --git a/certbot/tests/reverter_test.py b/certbot/tests/reverter_test.py index 5124c7d9f..2fb28862d 100644 --- a/certbot/tests/reverter_test.py +++ b/certbot/tests/reverter_test.py @@ -278,6 +278,7 @@ class TestFullCheckpointsReverter(test_util.ConfigTestCase): def setUp(self): super().setUp() from certbot.reverter import Reverter + # Disable spurious errors... logging.disable(logging.CRITICAL) diff --git a/certbot/tests/util_test.py b/certbot/tests/util_test.py index e9b5ddef2..0904c028f 100644 --- a/certbot/tests/util_test.py +++ b/certbot/tests/util_test.py @@ -121,6 +121,7 @@ class LockDirUntilExit(test_util.TempDirTestCase): registered_func = mock_register.call_args[0][0] from certbot import util + # Despite lock_dir_until_exit has been called twice to subdir, its lock should have been # added only once. So we expect to have two lock references: for self.tempdir and subdir self.assertEqual(len(util._LOCKS), 2) # pylint: disable=protected-access diff --git a/letstest/letstest/multitester.py b/letstest/letstest/multitester.py index a74e3f01d..c213a8637 100644 --- a/letstest/letstest/multitester.py +++ b/letstest/letstest/multitester.py @@ -41,10 +41,9 @@ import urllib.request as urllib_request import boto3 from botocore.exceptions import ClientError -import yaml - from fabric import Config from fabric import Connection +import yaml # Command line parser #------------------------------------------------------------------------------- diff --git a/letstest/scripts/version.py b/letstest/scripts/version.py index 6e538b032..dd8f1e3f3 100755 --- a/letstest/scripts/version.py +++ b/letstest/scripts/version.py @@ -5,7 +5,10 @@ Provides a simple utility for determining the Certbot version number """ from __future__ import print_function -from os.path import abspath, dirname, join + +from os.path import abspath +from os.path import dirname +from os.path import join import re diff --git a/tests/modification-check.py b/tests/modification-check.py index d685225a8..1d56d3442 100755 --- a/tests/modification-check.py +++ b/tests/modification-check.py @@ -4,7 +4,6 @@ import hashlib import os - # Relative to the root of the Certbot repo, these files are expected to exist # and have the SHA-256 hashes contained in this dictionary. These hashes were # taken from our v1.14.0 tag which was the last release we intended to make diff --git a/tools/finish_release.py b/tools/finish_release.py index bf6a14d9f..723f38004 100755 --- a/tools/finish_release.py +++ b/tools/finish_release.py @@ -26,16 +26,16 @@ release with that name already exists. """ import argparse +import getpass import glob import os.path import re import subprocess import sys import tempfile -import getpass -from azure.devops.connection import Connection from zipfile import ZipFile +from azure.devops.connection import Connection import requests # Path to the root directory of the Certbot repository containing this script diff --git a/tools/install_and_test.py b/tools/install_and_test.py index 1c84de96f..37864397e 100755 --- a/tools/install_and_test.py +++ b/tools/install_and_test.py @@ -10,6 +10,7 @@ import re import subprocess import sys + def call_with_print(command): print(command) subprocess.check_call(command, shell=True) From 057524aa52fce8a300e48fcdaa04ea41acac9e09 Mon Sep 17 00:00:00 2001 From: alexzorin Date: Sat, 11 Feb 2023 06:15:42 +1100 Subject: [PATCH 34/57] certbot-ci: fix crash in and simplify manual_http_hooks (#9570) There is a typo (`request` instead of `requests`) in the `auth.py` generated by this function: https://github.com/certbot/certbot/blob/d792d398134f4f8b67debaf82e6e75635409c627/certbot-ci/certbot_integration_tests/utils/misc.py#L184-L191 that has [never ever succeeded](https://gist.github.com/alexzorin/ff2686b7123cea49f1e4107d1e7d95f5#file-master-log-L203-L208). Moreover, this polling code is not necessary because `create_http_server` already polls until the HTTP server to come up, and the file we wrote to disk is guaranteed is immediately visible by the web server anyway. * certbot-ci: fix crash in and simplify manual_http_hooks * remove superfluous format argument * remove unused argument --- .../certbot_tests/test_main.py | 2 +- .../certbot_integration_tests/utils/misc.py | 18 ++---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py index 53f09b341..6df79c7f9 100644 --- a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py +++ b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py @@ -118,7 +118,7 @@ def test_http_01(context: IntegrationTestsContext) -> None: def test_manual_http_auth(context: IntegrationTestsContext) -> None: """Test the HTTP-01 challenge using manual plugin.""" with misc.create_http_server(context.http_01_port) as webroot,\ - misc.manual_http_hooks(webroot, context.http_01_port) as scripts: + misc.manual_http_hooks(webroot) as scripts: certname = context.get_domain() context.certbot([ diff --git a/certbot-ci/certbot_integration_tests/utils/misc.py b/certbot-ci/certbot_integration_tests/utils/misc.py index 558b96d40..22159c1fa 100644 --- a/certbot-ci/certbot_integration_tests/utils/misc.py +++ b/certbot-ci/certbot_integration_tests/utils/misc.py @@ -158,14 +158,12 @@ set -e @contextlib.contextmanager -def manual_http_hooks(http_server_root: str, - http_port: int) -> Generator[Tuple[str, str], None, None]: +def manual_http_hooks(http_server_root: str) -> Generator[Tuple[str, str], None, None]: """ Generate suitable http-01 hooks command for test purpose in the given HTTP server webroot directory. These hooks command use temporary python scripts that are deleted upon context exit. :param str http_server_root: path to the HTTP server configured to serve http-01 challenges - :param int http_port: HTTP port that the HTTP server listen on :return (str, str): a tuple containing the authentication hook and cleanup hook commands """ tempdir = tempfile.mkdtemp() @@ -175,24 +173,12 @@ def manual_http_hooks(http_server_root: str, file_h.write('''\ #!/usr/bin/env python import os -import requests -import time -import sys challenge_dir = os.path.join('{0}', '.well-known', 'acme-challenge') os.makedirs(challenge_dir) challenge_file = os.path.join(challenge_dir, os.environ.get('CERTBOT_TOKEN')) with open(challenge_file, 'w') as file_h: file_h.write(os.environ.get('CERTBOT_VALIDATION')) -url = 'http://localhost:{1}/.well-known/acme-challenge/' + os.environ.get('CERTBOT_TOKEN') -for _ in range(0, 10): - time.sleep(1) - try: - if request.get(url).status_code == 200: - sys.exit(0) - except requests.exceptions.ConnectionError: - pass -raise ValueError('Error, url did not respond after 10 attempts: {{0}}'.format(url)) -'''.format(http_server_root.replace('\\', '\\\\'), http_port)) +'''.format(http_server_root.replace('\\', '\\\\'))) os.chmod(auth_script_path, 0o755) cleanup_script_path = os.path.join(tempdir, 'cleanup.py') From dc07dfd07b2c137630b931cc10f69ec0c41c1150 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 13 Feb 2023 11:44:42 -0800 Subject: [PATCH 35/57] Automatically run test files with pytest (#9576) * Switch to pytest git grep -l unittest.main | xargs sed -i 's/unittest.main()/sys.exit(pytest.main([__file__]))/g' git ls-files -m | xargs -I {} sh -c "echo 'import sys\nimport pytest' >> '{}'" isort --float-to-top . * add pytest dep * use sys.argv --- acme/tests/challenges_test.py | 4 +++- acme/tests/client_test.py | 4 +++- acme/tests/crypto_util_test.py | 4 +++- acme/tests/errors_test.py | 5 ++++- acme/tests/fields_test.py | 4 +++- acme/tests/jose_test.py | 5 ++++- acme/tests/jws_test.py | 4 +++- acme/tests/messages_test.py | 4 +++- acme/tests/standalone_test.py | 4 +++- acme/tests/util_test.py | 5 ++++- certbot-apache/setup.py | 5 +++++ certbot-apache/tests/autohsts_test.py | 5 ++++- certbot-apache/tests/centos_test.py | 5 ++++- certbot-apache/tests/complex_parsing_test.py | 5 ++++- .../tests/configurator_reverter_test.py | 5 ++++- certbot-apache/tests/configurator_test.py | 5 ++++- certbot-apache/tests/debian_test.py | 5 ++++- certbot-apache/tests/display_ops_test.py | 5 ++++- certbot-apache/tests/entrypoint_test.py | 5 ++++- certbot-apache/tests/fedora_test.py | 5 ++++- certbot-apache/tests/gentoo_test.py | 5 ++++- certbot-apache/tests/http_01_test.py | 5 ++++- certbot-apache/tests/obj_test.py | 5 ++++- certbot-apache/tests/parser_test.py | 5 ++++- .../tests/parsernode_configurator_test.py | 5 ++++- certbot-apache/tests/parsernode_test.py | 5 ++++- certbot-apache/tests/parsernode_util_test.py | 5 ++++- certbot-dns-cloudflare/setup.py | 5 +++++ .../tests/dns_cloudflare_test.py | 4 +++- certbot-dns-digitalocean/setup.py | 5 +++++ .../tests/dns_digitalocean_test.py | 4 +++- certbot-dns-dnsimple/setup.py | 5 +++++ .../tests/dns_dnsimple_test.py | 4 +++- certbot-dns-dnsmadeeasy/setup.py | 5 +++++ .../tests/dns_dnsmadeeasy_test.py | 4 +++- certbot-dns-gehirn/setup.py | 5 +++++ certbot-dns-gehirn/tests/dns_gehirn_test.py | 4 +++- certbot-dns-google/setup.py | 5 +++++ certbot-dns-google/tests/dns_google_test.py | 4 +++- certbot-dns-linode/setup.py | 5 +++++ certbot-dns-linode/tests/dns_linode_test.py | 5 ++++- certbot-dns-luadns/setup.py | 5 +++++ certbot-dns-luadns/tests/dns_luadns_test.py | 4 +++- certbot-dns-nsone/setup.py | 5 +++++ certbot-dns-nsone/tests/dns_nsone_test.py | 4 +++- certbot-dns-ovh/setup.py | 5 +++++ certbot-dns-ovh/tests/dns_ovh_test.py | 4 +++- certbot-dns-rfc2136/setup.py | 5 +++++ certbot-dns-rfc2136/tests/dns_rfc2136_test.py | 4 +++- certbot-dns-route53/setup.py | 5 +++++ certbot-dns-route53/tests/dns_route53_test.py | 4 +++- certbot-dns-sakuracloud/setup.py | 5 +++++ .../tests/dns_sakuracloud_test.py | 4 +++- certbot-nginx/setup.py | 7 +++++++ certbot-nginx/tests/configurator_test.py | 4 +++- certbot-nginx/tests/display_ops_test.py | 5 ++++- certbot-nginx/tests/http_01_test.py | 4 +++- certbot-nginx/tests/nginxparser_test.py | 4 +++- certbot-nginx/tests/obj_test.py | 5 ++++- certbot-nginx/tests/parser_obj_test.py | 5 ++++- certbot-nginx/tests/parser_test.py | 5 ++++- certbot/CHANGELOG.md | 1 + certbot/tests/account_test.py | 4 +++- certbot/tests/auth_handler_test.py | 4 +++- certbot/tests/cert_manager_test.py | 4 +++- certbot/tests/cli_test.py | 5 ++++- certbot/tests/client_test.py | 4 +++- certbot/tests/compat/filesystem_test.py | 5 ++++- certbot/tests/compat/misc_test.py | 5 ++++- certbot/tests/compat/os_test.py | 5 ++++- certbot/tests/configuration_test.py | 5 ++++- certbot/tests/crypto_util_test.py | 4 +++- certbot/tests/display/completer_test.py | 21 +++++++++++-------- certbot/tests/display/internal_util_test.py | 5 ++++- certbot/tests/display/obj_test.py | 5 ++++- certbot/tests/display/ops_test.py | 3 ++- certbot/tests/display/util_test.py | 5 ++++- certbot/tests/eff_test.py | 4 +++- certbot/tests/error_handler_test.py | 4 +++- certbot/tests/errors_test.py | 5 ++++- certbot/tests/helpful_test.py | 5 ++++- certbot/tests/hook_test.py | 5 ++++- certbot/tests/lock_test.py | 5 ++++- certbot/tests/log_test.py | 4 +++- certbot/tests/main_test.py | 3 ++- certbot/tests/ocsp_test.py | 4 +++- certbot/tests/plugins/common_test.py | 4 +++- certbot/tests/plugins/disco_test.py | 4 +++- .../tests/plugins/dns_common_lexicon_test.py | 5 ++++- certbot/tests/plugins/dns_common_test.py | 5 ++++- certbot/tests/plugins/enhancements_test.py | 5 ++++- certbot/tests/plugins/manual_test.py | 4 +++- certbot/tests/plugins/null_test.py | 5 ++++- certbot/tests/plugins/selection_test.py | 4 +++- certbot/tests/plugins/standalone_test.py | 4 +++- certbot/tests/plugins/storage_test.py | 5 ++++- certbot/tests/plugins/util_test.py | 5 ++++- certbot/tests/plugins/webroot_test.py | 4 +++- certbot/tests/renewal_test.py | 5 ++++- certbot/tests/renewupdater_test.py | 5 ++++- certbot/tests/reverter_test.py | 5 ++++- certbot/tests/storage_test.py | 4 +++- certbot/tests/util_test.py | 4 +++- 103 files changed, 391 insertions(+), 95 deletions(-) diff --git a/acme/tests/challenges_test.py b/acme/tests/challenges_test.py index 1a855788c..000451f78 100644 --- a/acme/tests/challenges_test.py +++ b/acme/tests/challenges_test.py @@ -1,4 +1,5 @@ """Tests for acme.challenges.""" +import sys import unittest from unittest import mock import urllib.parse as urllib_parse @@ -6,6 +7,7 @@ import urllib.parse as urllib_parse import josepy as jose from josepy.jwk import JWKEC import OpenSSL +import pytest import requests from acme import errors @@ -505,4 +507,4 @@ class JWSPayloadRFC8555Compliant(unittest.TestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/acme/tests/client_test.py b/acme/tests/client_test.py index 06f527e84..ee969683e 100644 --- a/acme/tests/client_test.py +++ b/acme/tests/client_test.py @@ -4,11 +4,13 @@ import copy import datetime import http.client as http_client import json +import sys from typing import Dict import unittest from unittest import mock import josepy as jose +import pytest import requests from acme import challenges @@ -792,4 +794,4 @@ class ClientNetworkWithMockedResponseTest(unittest.TestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/acme/tests/crypto_util_test.py b/acme/tests/crypto_util_test.py index 81f8fcdce..008430ac4 100644 --- a/acme/tests/crypto_util_test.py +++ b/acme/tests/crypto_util_test.py @@ -3,6 +3,7 @@ import ipaddress import itertools import socket import socketserver +import sys import threading import time from typing import List @@ -10,6 +11,7 @@ import unittest import josepy as jose import OpenSSL +import pytest from acme import errors import test_util @@ -351,4 +353,4 @@ class DumpPyopensslChainTest(unittest.TestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/acme/tests/errors_test.py b/acme/tests/errors_test.py index f325b284e..0e9f10fe1 100644 --- a/acme/tests/errors_test.py +++ b/acme/tests/errors_test.py @@ -1,7 +1,10 @@ """Tests for acme.errors.""" +import sys import unittest from unittest import mock +import pytest + class BadNonceTest(unittest.TestCase): """Tests for acme.errors.BadNonce.""" @@ -49,4 +52,4 @@ class PollErrorTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/acme/tests/fields_test.py b/acme/tests/fields_test.py index 68e5c9a7f..f07759397 100644 --- a/acme/tests/fields_test.py +++ b/acme/tests/fields_test.py @@ -1,9 +1,11 @@ """Tests for acme.fields.""" import datetime +import sys import unittest import warnings import josepy as jose +import pytest import pytz @@ -56,4 +58,4 @@ class RFC3339FieldTest(unittest.TestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/acme/tests/jose_test.py b/acme/tests/jose_test.py index 1564e0d38..b0b7194fe 100644 --- a/acme/tests/jose_test.py +++ b/acme/tests/jose_test.py @@ -1,7 +1,10 @@ """Tests for acme.jose shim.""" import importlib +import sys import unittest +import pytest + class JoseTest(unittest.TestCase): """Tests for acme.jose shim.""" @@ -51,4 +54,4 @@ class JoseTest(unittest.TestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/acme/tests/jws_test.py b/acme/tests/jws_test.py index 0787fb340..96e0e7d4d 100644 --- a/acme/tests/jws_test.py +++ b/acme/tests/jws_test.py @@ -1,7 +1,9 @@ """Tests for acme.jws.""" +import sys import unittest import josepy as jose +import pytest import test_util @@ -63,4 +65,4 @@ class JWSTest(unittest.TestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/acme/tests/messages_test.py b/acme/tests/messages_test.py index 7c1664ba4..22a22e228 100644 --- a/acme/tests/messages_test.py +++ b/acme/tests/messages_test.py @@ -1,11 +1,13 @@ """Tests for acme.messages.""" import contextlib +import sys from typing import Dict import unittest from unittest import mock import warnings import josepy as jose +import pytest from acme import challenges import test_util @@ -520,4 +522,4 @@ class JWSPayloadRFC8555Compliant(unittest.TestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/acme/tests/standalone_test.py b/acme/tests/standalone_test.py index db4e39b5a..f9bc0c58c 100644 --- a/acme/tests/standalone_test.py +++ b/acme/tests/standalone_test.py @@ -2,12 +2,14 @@ import http.client as http_client import socket import socketserver +import sys import threading from typing import Set import unittest from unittest import mock import josepy as jose +import pytest import requests from acme import challenges @@ -267,4 +269,4 @@ class HTTP01DualNetworkedServersTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/acme/tests/util_test.py b/acme/tests/util_test.py index 00aa8b02d..372694b67 100644 --- a/acme/tests/util_test.py +++ b/acme/tests/util_test.py @@ -1,6 +1,9 @@ """Tests for acme.util.""" +import sys import unittest +import pytest + class MapKeysTest(unittest.TestCase): """Tests for acme.util.map_keys.""" @@ -13,4 +16,4 @@ class MapKeysTest(unittest.TestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index 3eb927042..ab545be03 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -17,6 +17,10 @@ dev_extras = [ 'apacheconfig>=0.3.2', ] +test_extras = [ + 'pytest', +] + setup( name='certbot-apache', version=version, @@ -52,6 +56,7 @@ setup( install_requires=install_requires, extras_require={ 'dev': dev_extras, + 'test': test_extras, }, entry_points={ 'certbot.plugins': [ diff --git a/certbot-apache/tests/autohsts_test.py b/certbot-apache/tests/autohsts_test.py index 70ed2ca1a..b2e071695 100644 --- a/certbot-apache/tests/autohsts_test.py +++ b/certbot-apache/tests/autohsts_test.py @@ -1,9 +1,12 @@ # pylint: disable=too-many-lines """Test for certbot_apache._internal.configurator AutoHSTS functionality""" import re +import sys import unittest from unittest import mock +import pytest + from certbot import errors from certbot_apache._internal import constants import util @@ -180,4 +183,4 @@ class AutoHSTSTest(util.ApacheTest): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/centos_test.py b/certbot-apache/tests/centos_test.py index 71cc6df00..5aba89388 100644 --- a/certbot-apache/tests/centos_test.py +++ b/certbot-apache/tests/centos_test.py @@ -1,7 +1,10 @@ """Test for certbot_apache._internal.configurator for Centos overrides""" +import sys import unittest from unittest import mock +import pytest + from certbot import errors from certbot.compat import filesystem from certbot.compat import os @@ -238,4 +241,4 @@ class MultipleVhostsTestCentOS(util.ApacheTest): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/complex_parsing_test.py b/certbot-apache/tests/complex_parsing_test.py index 973af302a..c26a65b64 100644 --- a/certbot-apache/tests/complex_parsing_test.py +++ b/certbot-apache/tests/complex_parsing_test.py @@ -1,7 +1,10 @@ """Tests for certbot_apache._internal.parser.""" import shutil +import sys import unittest +import pytest + from certbot import errors from certbot.compat import os import util @@ -124,4 +127,4 @@ class ComplexParserTest(util.ParserTest): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/configurator_reverter_test.py b/certbot-apache/tests/configurator_reverter_test.py index fe0dfb39d..b0ddacfed 100644 --- a/certbot-apache/tests/configurator_reverter_test.py +++ b/certbot-apache/tests/configurator_reverter_test.py @@ -1,8 +1,11 @@ """Test for certbot_apache._internal.configurator implementations of reverter""" import shutil +import sys import unittest from unittest import mock +import pytest + from certbot import errors import util @@ -73,4 +76,4 @@ class ConfiguratorReverterTest(util.ApacheTest): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/configurator_test.py b/certbot-apache/tests/configurator_test.py index f1f9a5e0d..e9ac734f9 100644 --- a/certbot-apache/tests/configurator_test.py +++ b/certbot-apache/tests/configurator_test.py @@ -3,10 +3,13 @@ import copy import shutil import socket +import sys import tempfile import unittest from unittest import mock +import pytest + from acme import challenges from certbot import achallenges from certbot import crypto_util @@ -1773,4 +1776,4 @@ class InstallSslOptionsConfTest(util.ApacheTest): self.assertEqual(self.config._open_module_file("/nonsense/"), "testing 12 3") if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/debian_test.py b/certbot-apache/tests/debian_test.py index facc65107..775b542a2 100644 --- a/certbot-apache/tests/debian_test.py +++ b/certbot-apache/tests/debian_test.py @@ -1,8 +1,11 @@ """Test for certbot_apache._internal.configurator for Debian overrides""" import shutil +import sys import unittest from unittest import mock +import pytest + from certbot import errors from certbot.compat import os from certbot.tests import util as certbot_util @@ -211,4 +214,4 @@ class MultipleVhostsTestDebian(util.ApacheTest): errors.MisconfigurationError, self.config.enable_mod, "ssl") if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/display_ops_test.py b/certbot-apache/tests/display_ops_test.py index 26927ffad..d730f7c78 100644 --- a/certbot-apache/tests/display_ops_test.py +++ b/certbot-apache/tests/display_ops_test.py @@ -1,7 +1,10 @@ """Test certbot_apache._internal.display_ops.""" +import sys import unittest from unittest import mock +import pytest + from certbot import errors from certbot.display import util as display_util from certbot.tests import util as certbot_util @@ -100,4 +103,4 @@ class SelectVhostTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/entrypoint_test.py b/certbot-apache/tests/entrypoint_test.py index 0b9644f09..c6dbd53b2 100644 --- a/certbot-apache/tests/entrypoint_test.py +++ b/certbot-apache/tests/entrypoint_test.py @@ -1,7 +1,10 @@ """Test for certbot_apache._internal.entrypoint for override class resolution""" +import sys import unittest from unittest import mock +import pytest + from certbot_apache._internal import configurator from certbot_apache._internal import entrypoint @@ -43,4 +46,4 @@ class EntryPointTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/fedora_test.py b/certbot-apache/tests/fedora_test.py index 4ff704aaf..faf6e8ccc 100644 --- a/certbot-apache/tests/fedora_test.py +++ b/certbot-apache/tests/fedora_test.py @@ -1,7 +1,10 @@ """Test for certbot_apache._internal.configurator for Fedora 29+ overrides""" +import sys import unittest from unittest import mock +import pytest + from certbot import errors from certbot.compat import filesystem from certbot.compat import os @@ -190,4 +193,4 @@ class MultipleVhostsTestFedora(util.ApacheTest): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/gentoo_test.py b/certbot-apache/tests/gentoo_test.py index 4df46e70f..201cccb85 100644 --- a/certbot-apache/tests/gentoo_test.py +++ b/certbot-apache/tests/gentoo_test.py @@ -1,7 +1,10 @@ """Test for certbot_apache._internal.configurator for Gentoo overrides""" +import sys import unittest from unittest import mock +import pytest + from certbot import errors from certbot.compat import filesystem from certbot.compat import os @@ -133,4 +136,4 @@ class MultipleVhostsTestGentoo(util.ApacheTest): self.assertEqual(mock_run_script.call_count, 3) if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/http_01_test.py b/certbot-apache/tests/http_01_test.py index 6ece4c6be..5fbf52bf5 100644 --- a/certbot-apache/tests/http_01_test.py +++ b/certbot-apache/tests/http_01_test.py @@ -1,9 +1,12 @@ """Test for certbot_apache._internal.http_01.""" import errno +import sys from typing import List import unittest from unittest import mock +import pytest + from acme import challenges from certbot import achallenges from certbot import errors @@ -220,4 +223,4 @@ class ApacheHttp01Test(util.ApacheTest): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/obj_test.py b/certbot-apache/tests/obj_test.py index 411ec21e9..a2053dc43 100644 --- a/certbot-apache/tests/obj_test.py +++ b/certbot-apache/tests/obj_test.py @@ -1,6 +1,9 @@ """Tests for certbot_apache._internal.obj.""" +import sys import unittest +import pytest + class VirtualHostTest(unittest.TestCase): """Test the VirtualHost class.""" @@ -137,4 +140,4 @@ class AddrTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/parser_test.py b/certbot-apache/tests/parser_test.py index 77b2f34ec..a5950804c 100644 --- a/certbot-apache/tests/parser_test.py +++ b/certbot-apache/tests/parser_test.py @@ -1,8 +1,11 @@ """Tests for certbot_apache._internal.parser.""" import shutil +import sys import unittest from unittest import mock +import pytest + from certbot import errors from certbot.compat import os import util @@ -400,4 +403,4 @@ class ParserInitTest(util.ApacheTest): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/parsernode_configurator_test.py b/certbot-apache/tests/parsernode_configurator_test.py index 6c153acc4..ea704c3a9 100644 --- a/certbot-apache/tests/parsernode_configurator_test.py +++ b/certbot-apache/tests/parsernode_configurator_test.py @@ -1,7 +1,10 @@ """Tests for ApacheConfigurator for AugeasParserNode classes""" +import sys import unittest from unittest import mock +import pytest + import util try: @@ -40,4 +43,4 @@ class ConfiguratorParserNodeTest(util.ApacheTest): # pylint: disable=too-many-p if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/parsernode_test.py b/certbot-apache/tests/parsernode_test.py index 4ea5f8415..35eb53414 100644 --- a/certbot-apache/tests/parsernode_test.py +++ b/certbot-apache/tests/parsernode_test.py @@ -1,7 +1,10 @@ """ Tests for ParserNode interface """ +import sys import unittest +import pytest + from certbot_apache._internal import interfaces from certbot_apache._internal import parsernode_util as util @@ -125,4 +128,4 @@ class ParserNodeTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/parsernode_util_test.py b/certbot-apache/tests/parsernode_util_test.py index 715388da5..fd2e35ab5 100644 --- a/certbot-apache/tests/parsernode_util_test.py +++ b/certbot-apache/tests/parsernode_util_test.py @@ -1,6 +1,9 @@ """ Tests for ParserNode utils """ +import sys import unittest +import pytest + from certbot_apache._internal import parsernode_util as util @@ -112,4 +115,4 @@ class ParserNodeUtilTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index 2891423c0..3ac78a942 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -30,6 +30,10 @@ docs_extras = [ 'sphinx_rtd_theme', ] +test_extras = [ + 'pytest', +] + setup( name='certbot-dns-cloudflare', version=version, @@ -65,6 +69,7 @@ setup( install_requires=install_requires, extras_require={ 'docs': docs_extras, + 'test': test_extras, }, entry_points={ 'certbot.plugins': [ diff --git a/certbot-dns-cloudflare/tests/dns_cloudflare_test.py b/certbot-dns-cloudflare/tests/dns_cloudflare_test.py index cd73adc8f..40f3ca2c0 100644 --- a/certbot-dns-cloudflare/tests/dns_cloudflare_test.py +++ b/certbot-dns-cloudflare/tests/dns_cloudflare_test.py @@ -1,9 +1,11 @@ """Tests for certbot_dns_cloudflare._internal.dns_cloudflare.""" +import sys import unittest from unittest import mock import CloudFlare +import pytest from certbot import errors from certbot.compat import os @@ -245,4 +247,4 @@ class CloudflareClientTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index de8a3e98f..ca1b1612e 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -30,6 +30,10 @@ docs_extras = [ 'sphinx_rtd_theme', ] +test_extras = [ + 'pytest', +] + setup( name='certbot-dns-digitalocean', version=version, @@ -65,6 +69,7 @@ setup( install_requires=install_requires, extras_require={ 'docs': docs_extras, + 'test': test_extras, }, entry_points={ 'certbot.plugins': [ diff --git a/certbot-dns-digitalocean/tests/dns_digitalocean_test.py b/certbot-dns-digitalocean/tests/dns_digitalocean_test.py index 8fdee38f3..a70768e98 100644 --- a/certbot-dns-digitalocean/tests/dns_digitalocean_test.py +++ b/certbot-dns-digitalocean/tests/dns_digitalocean_test.py @@ -1,9 +1,11 @@ """Tests for certbot_dns_digitalocean._internal.dns_digitalocean.""" +import sys import unittest from unittest import mock import digitalocean +import pytest from certbot import errors from certbot.compat import os @@ -172,4 +174,4 @@ class DigitalOceanClientTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index 1395fd1ef..5760b6381 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -32,6 +32,10 @@ docs_extras = [ 'sphinx_rtd_theme', ] +test_extras = [ + 'pytest', +] + setup( name='certbot-dns-dnsimple', version=version, @@ -67,6 +71,7 @@ setup( install_requires=install_requires, extras_require={ 'docs': docs_extras, + 'test': test_extras, }, entry_points={ 'certbot.plugins': [ diff --git a/certbot-dns-dnsimple/tests/dns_dnsimple_test.py b/certbot-dns-dnsimple/tests/dns_dnsimple_test.py index 0e28f43b2..31a91be0f 100644 --- a/certbot-dns-dnsimple/tests/dns_dnsimple_test.py +++ b/certbot-dns-dnsimple/tests/dns_dnsimple_test.py @@ -1,8 +1,10 @@ """Tests for certbot_dns_dnsimple._internal.dns_dnsimple.""" +import sys import unittest from unittest import mock +import pytest from requests.exceptions import HTTPError from certbot.compat import os @@ -48,4 +50,4 @@ class DNSimpleLexiconClientTest(unittest.TestCase, dns_test_common_lexicon.BaseL if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index a12950fa1..103b8c3e9 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -30,6 +30,10 @@ docs_extras = [ 'sphinx_rtd_theme', ] +test_extras = [ + 'pytest', +] + setup( name='certbot-dns-dnsmadeeasy', version=version, @@ -65,6 +69,7 @@ setup( install_requires=install_requires, extras_require={ 'docs': docs_extras, + 'test': test_extras, }, entry_points={ 'certbot.plugins': [ diff --git a/certbot-dns-dnsmadeeasy/tests/dns_dnsmadeeasy_test.py b/certbot-dns-dnsmadeeasy/tests/dns_dnsmadeeasy_test.py index 46f5895a8..2295e83cf 100644 --- a/certbot-dns-dnsmadeeasy/tests/dns_dnsmadeeasy_test.py +++ b/certbot-dns-dnsmadeeasy/tests/dns_dnsmadeeasy_test.py @@ -1,8 +1,10 @@ """Tests for certbot_dns_dnsmadeeasy._internal.dns_dnsmadeeasy.""" +import sys import unittest from unittest import mock +import pytest from requests.exceptions import HTTPError from certbot.compat import os @@ -53,4 +55,4 @@ class DNSMadeEasyLexiconClientTest(unittest.TestCase, if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 88f282fcf..77cd937b3 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -30,6 +30,10 @@ docs_extras = [ 'sphinx_rtd_theme', ] +test_extras = [ + 'pytest', +] + setup( name='certbot-dns-gehirn', version=version, @@ -65,6 +69,7 @@ setup( install_requires=install_requires, extras_require={ 'docs': docs_extras, + 'test': test_extras, }, entry_points={ 'certbot.plugins': [ diff --git a/certbot-dns-gehirn/tests/dns_gehirn_test.py b/certbot-dns-gehirn/tests/dns_gehirn_test.py index b982e3e1b..b15e36cab 100644 --- a/certbot-dns-gehirn/tests/dns_gehirn_test.py +++ b/certbot-dns-gehirn/tests/dns_gehirn_test.py @@ -1,8 +1,10 @@ """Tests for certbot_dns_gehirn._internal.dns_gehirn.""" +import sys import unittest from unittest import mock +import pytest from requests.exceptions import HTTPError from certbot.compat import os @@ -52,4 +54,4 @@ class GehirnLexiconClientTest(unittest.TestCase, dns_test_common_lexicon.BaseLex if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index 632a690f1..eb4152456 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -33,6 +33,10 @@ docs_extras = [ 'sphinx_rtd_theme', ] +test_extras = [ + 'pytest', +] + setup( name='certbot-dns-google', version=version, @@ -68,6 +72,7 @@ setup( install_requires=install_requires, extras_require={ 'docs': docs_extras, + 'test': test_extras, }, entry_points={ 'certbot.plugins': [ diff --git a/certbot-dns-google/tests/dns_google_test.py b/certbot-dns-google/tests/dns_google_test.py index 1d27a39a8..58614d1ac 100644 --- a/certbot-dns-google/tests/dns_google_test.py +++ b/certbot-dns-google/tests/dns_google_test.py @@ -1,5 +1,6 @@ """Tests for certbot_dns_google._internal.dns_google.""" +import sys import unittest from unittest import mock @@ -7,6 +8,7 @@ from googleapiclient import discovery from googleapiclient.errors import Error from googleapiclient.http import HttpMock from httplib2 import ServerNotFoundError +import pytest from certbot import errors from certbot.compat import os @@ -410,4 +412,4 @@ class DummyResponse: if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index 36bee97e8..3ff9ad5a0 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -30,6 +30,10 @@ docs_extras = [ 'sphinx_rtd_theme', ] +test_extras = [ + 'pytest', +] + setup( name='certbot-dns-linode', version=version, @@ -65,6 +69,7 @@ setup( install_requires=install_requires, extras_require={ 'docs': docs_extras, + 'test': test_extras, }, entry_points={ 'certbot.plugins': [ diff --git a/certbot-dns-linode/tests/dns_linode_test.py b/certbot-dns-linode/tests/dns_linode_test.py index c227ef4b5..be5a7b50b 100644 --- a/certbot-dns-linode/tests/dns_linode_test.py +++ b/certbot-dns-linode/tests/dns_linode_test.py @@ -1,8 +1,11 @@ """Tests for certbot_dns_linode._internal.dns_linode.""" +import sys import unittest from unittest import mock +import pytest + from certbot import errors from certbot.compat import os from certbot.plugins import dns_test_common @@ -144,4 +147,4 @@ class Linode4LexiconClientTest(unittest.TestCase, dns_test_common_lexicon.BaseLe if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index c6b889548..729e9950c 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -30,6 +30,10 @@ docs_extras = [ 'sphinx_rtd_theme', ] +test_extras = [ + 'pytest', +] + setup( name='certbot-dns-luadns', version=version, @@ -65,6 +69,7 @@ setup( install_requires=install_requires, extras_require={ 'docs': docs_extras, + 'test': test_extras, }, entry_points={ 'certbot.plugins': [ diff --git a/certbot-dns-luadns/tests/dns_luadns_test.py b/certbot-dns-luadns/tests/dns_luadns_test.py index 3c1ac6841..2cade9f9a 100644 --- a/certbot-dns-luadns/tests/dns_luadns_test.py +++ b/certbot-dns-luadns/tests/dns_luadns_test.py @@ -1,8 +1,10 @@ """Tests for certbot_dns_luadns._internal.dns_luadns.""" +import sys import unittest from unittest import mock +import pytest from requests.exceptions import HTTPError from certbot.compat import os @@ -49,4 +51,4 @@ class LuaDNSLexiconClientTest(unittest.TestCase, dns_test_common_lexicon.BaseLex if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index cad383c2b..039cbb180 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -30,6 +30,10 @@ docs_extras = [ 'sphinx_rtd_theme', ] +test_extras = [ + 'pytest', +] + setup( name='certbot-dns-nsone', version=version, @@ -65,6 +69,7 @@ setup( install_requires=install_requires, extras_require={ 'docs': docs_extras, + 'test': test_extras, }, entry_points={ 'certbot.plugins': [ diff --git a/certbot-dns-nsone/tests/dns_nsone_test.py b/certbot-dns-nsone/tests/dns_nsone_test.py index 13ea09b3d..f4da5b4cc 100644 --- a/certbot-dns-nsone/tests/dns_nsone_test.py +++ b/certbot-dns-nsone/tests/dns_nsone_test.py @@ -1,8 +1,10 @@ """Tests for certbot_dns_nsone._internal.dns_nsone.""" +import sys import unittest from unittest import mock +import pytest from requests.exceptions import HTTPError from certbot.compat import os @@ -49,4 +51,4 @@ class NS1LexiconClientTest(unittest.TestCase, dns_test_common_lexicon.BaseLexico if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index a8a83018b..8748f6293 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -30,6 +30,10 @@ docs_extras = [ 'sphinx_rtd_theme', ] +test_extras = [ + 'pytest', +] + setup( name='certbot-dns-ovh', version=version, @@ -65,6 +69,7 @@ setup( install_requires=install_requires, extras_require={ 'docs': docs_extras, + 'test': test_extras, }, entry_points={ 'certbot.plugins': [ diff --git a/certbot-dns-ovh/tests/dns_ovh_test.py b/certbot-dns-ovh/tests/dns_ovh_test.py index 7eb767b70..a83ec8470 100644 --- a/certbot-dns-ovh/tests/dns_ovh_test.py +++ b/certbot-dns-ovh/tests/dns_ovh_test.py @@ -1,8 +1,10 @@ """Tests for certbot_dns_ovh._internal.dns_ovh.""" +import sys import unittest from unittest import mock +import pytest from requests.exceptions import HTTPError from certbot.compat import os @@ -59,4 +61,4 @@ class OVHLexiconClientTest(unittest.TestCase, dns_test_common_lexicon.BaseLexico if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index c3fdeb864..476c8a4ab 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -30,6 +30,10 @@ docs_extras = [ 'sphinx_rtd_theme', ] +test_extras = [ + 'pytest', +] + setup( name='certbot-dns-rfc2136', version=version, @@ -65,6 +69,7 @@ setup( install_requires=install_requires, extras_require={ 'docs': docs_extras, + 'test': test_extras, }, entry_points={ 'certbot.plugins': [ diff --git a/certbot-dns-rfc2136/tests/dns_rfc2136_test.py b/certbot-dns-rfc2136/tests/dns_rfc2136_test.py index 1f91d3cb6..19943d680 100644 --- a/certbot-dns-rfc2136/tests/dns_rfc2136_test.py +++ b/certbot-dns-rfc2136/tests/dns_rfc2136_test.py @@ -1,11 +1,13 @@ """Tests for certbot_dns_rfc2136._internal.dns_rfc2136.""" +import sys import unittest from unittest import mock import dns.flags import dns.rcode import dns.tsig +import pytest from certbot import errors from certbot.compat import os @@ -234,4 +236,4 @@ class RFC2136ClientTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index 651413516..596146d05 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -30,6 +30,10 @@ docs_extras = [ 'sphinx_rtd_theme', ] +test_extras = [ + 'pytest', +] + setup( name='certbot-dns-route53', version=version, @@ -65,6 +69,7 @@ setup( keywords=['certbot', 'route53', 'aws'], extras_require={ 'docs': docs_extras, + 'test': test_extras, }, entry_points={ 'certbot.plugins': [ diff --git a/certbot-dns-route53/tests/dns_route53_test.py b/certbot-dns-route53/tests/dns_route53_test.py index bdc70e048..3aa8f2b01 100644 --- a/certbot-dns-route53/tests/dns_route53_test.py +++ b/certbot-dns-route53/tests/dns_route53_test.py @@ -1,10 +1,12 @@ """Tests for certbot_dns_route53._internal.dns_route53.Authenticator""" +import sys import unittest from unittest import mock from botocore.exceptions import ClientError from botocore.exceptions import NoCredentialsError +import pytest from certbot import errors from certbot.compat import os @@ -257,4 +259,4 @@ class ClientTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index 235ab8d10..464380ccc 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -30,6 +30,10 @@ docs_extras = [ 'sphinx_rtd_theme', ] +test_extras = [ + 'pytest', +] + setup( name='certbot-dns-sakuracloud', version=version, @@ -65,6 +69,7 @@ setup( install_requires=install_requires, extras_require={ 'docs': docs_extras, + 'test': test_extras, }, entry_points={ 'certbot.plugins': [ diff --git a/certbot-dns-sakuracloud/tests/dns_sakuracloud_test.py b/certbot-dns-sakuracloud/tests/dns_sakuracloud_test.py index a1abf7b78..2e8fccb55 100644 --- a/certbot-dns-sakuracloud/tests/dns_sakuracloud_test.py +++ b/certbot-dns-sakuracloud/tests/dns_sakuracloud_test.py @@ -1,8 +1,10 @@ """Tests for certbot_dns_sakuracloud._internal.dns_sakuracloud.""" +import sys import unittest from unittest import mock +import pytest from requests.exceptions import HTTPError from certbot.compat import os @@ -53,4 +55,4 @@ class SakuraCloudLexiconClientTest(unittest.TestCase, if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index 77dc3d257..a2beec1d6 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -14,6 +14,10 @@ install_requires = [ 'setuptools>=41.6.0', ] +test_extras = [ + 'pytest', +] + setup( name='certbot-nginx', version=version, @@ -47,6 +51,9 @@ setup( packages=find_packages(), include_package_data=True, install_requires=install_requires, + extras_require={ + 'test': test_extras, + }, entry_points={ 'certbot.plugins': [ 'nginx = certbot_nginx._internal.configurator:NginxConfigurator', diff --git a/certbot-nginx/tests/configurator_test.py b/certbot-nginx/tests/configurator_test.py index 12dc61a38..50e02f5c3 100644 --- a/certbot-nginx/tests/configurator_test.py +++ b/certbot-nginx/tests/configurator_test.py @@ -1,8 +1,10 @@ """Test for certbot_nginx._internal.configurator.""" +import sys import unittest from unittest import mock import OpenSSL +import pytest from acme import challenges from acme import messages @@ -1133,4 +1135,4 @@ class DetermineDefaultServerRootTest(certbot_test_util.ConfigTestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-nginx/tests/display_ops_test.py b/certbot-nginx/tests/display_ops_test.py index 19f51e7e8..7c3e878bc 100644 --- a/certbot-nginx/tests/display_ops_test.py +++ b/certbot-nginx/tests/display_ops_test.py @@ -1,6 +1,9 @@ """Test certbot_nginx._internal.display_ops.""" +import sys import unittest +import pytest + from certbot.display import util as display_util from certbot.tests import util as certbot_util from certbot_nginx._internal import parser @@ -40,4 +43,4 @@ class SelectVhostMultiTest(util.NginxTest): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-nginx/tests/http_01_test.py b/certbot-nginx/tests/http_01_test.py index 05be06202..2a03255a4 100644 --- a/certbot-nginx/tests/http_01_test.py +++ b/certbot-nginx/tests/http_01_test.py @@ -1,8 +1,10 @@ """Tests for certbot_nginx._internal.http_01""" +import sys import unittest from unittest import mock import josepy as jose +import pytest from acme import challenges from certbot import achallenges @@ -228,4 +230,4 @@ class HttpPerformTest(util.NginxTest): self.assertEqual(addrs, [http_addr]) if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-nginx/tests/nginxparser_test.py b/certbot-nginx/tests/nginxparser_test.py index 3713f16e4..7f9847db8 100644 --- a/certbot-nginx/tests/nginxparser_test.py +++ b/certbot-nginx/tests/nginxparser_test.py @@ -1,10 +1,12 @@ """Test for certbot_nginx._internal.nginxparser.""" import copy import operator +import sys import tempfile import unittest from pyparsing import ParseException +import pytest from certbot_nginx._internal.nginxparser import dump from certbot_nginx._internal.nginxparser import dumps @@ -508,4 +510,4 @@ class TestUnspacedList(unittest.TestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-nginx/tests/obj_test.py b/certbot-nginx/tests/obj_test.py index 67ca40f1b..ef8255ee9 100644 --- a/certbot-nginx/tests/obj_test.py +++ b/certbot-nginx/tests/obj_test.py @@ -1,7 +1,10 @@ """Test the helper objects in certbot_nginx._internal.obj.""" import itertools +import sys import unittest +import pytest + class AddrTest(unittest.TestCase): """Test the Addr class.""" @@ -226,4 +229,4 @@ class VirtualHostTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-nginx/tests/parser_obj_test.py b/certbot-nginx/tests/parser_obj_test.py index c2243f5be..e0a8114a9 100644 --- a/certbot-nginx/tests/parser_obj_test.py +++ b/certbot-nginx/tests/parser_obj_test.py @@ -1,8 +1,11 @@ """ Tests for functions and classes in parser_obj.py """ +import sys import unittest from unittest import mock +import pytest + from certbot_nginx._internal.parser_obj import COMMENT_BLOCK from certbot_nginx._internal.parser_obj import parse_raw @@ -256,4 +259,4 @@ class StatementsTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-nginx/tests/parser_test.py b/certbot-nginx/tests/parser_test.py index 4aaa00ea0..e9280c787 100644 --- a/certbot-nginx/tests/parser_test.py +++ b/certbot-nginx/tests/parser_test.py @@ -2,10 +2,13 @@ import glob import re import shutil +import sys from typing import List import unittest from unittest import mock +import pytest + from certbot import errors from certbot.compat import os from certbot_nginx._internal import nginxparser @@ -544,4 +547,4 @@ class NginxParserTest(util.NginxTest): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index ab1bcc963..a3b8b23f5 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -15,6 +15,7 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). * Certbot will now only keep the current and 5 previous certificates in the `/etc/letsencrypt/archive` directory for each certificate lineage. Any prior certificates will be automatically deleted upon renewal. This number may be further lowered in future releases. * As always, users should only reference the certificate files within `/etc/letsencrypt/live` and never use `/etc/letsencrypt/archive` directly. See [Where are my certificates?](https://eff-certbot.readthedocs.io/en/stable/using.html#where-are-my-certificates) in the Certbot User Guide. * `certbot.configuration.NamespaceConfig.key_dir` and `.csr_dir` are now deprecated. +* All Certbot components now require `pytest` to run tests. ### Fixed diff --git a/certbot/tests/account_test.py b/certbot/tests/account_test.py index d60da44c1..f076b2096 100644 --- a/certbot/tests/account_test.py +++ b/certbot/tests/account_test.py @@ -1,10 +1,12 @@ """Tests for certbot._internal.account.""" import datetime import json +import sys import unittest from unittest import mock import josepy as jose +import pytest import pytz from acme import messages @@ -330,4 +332,4 @@ class AccountFileStorageTest(test_util.ConfigTestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/auth_handler_test.py b/certbot/tests/auth_handler_test.py index 0af351c80..f4415e5ce 100644 --- a/certbot/tests/auth_handler_test.py +++ b/certbot/tests/auth_handler_test.py @@ -1,10 +1,12 @@ """Tests for certbot._internal.auth_handler.""" import datetime import logging +import sys import unittest from unittest import mock from josepy import b64encode +import pytest from acme import challenges from acme import client as acme_client @@ -592,4 +594,4 @@ def gen_dom_authzr(domain, challs): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/cert_manager_test.py b/certbot/tests/cert_manager_test.py index 08f733bbe..659a6fc47 100644 --- a/certbot/tests/cert_manager_test.py +++ b/certbot/tests/cert_manager_test.py @@ -3,11 +3,13 @@ # pylint: disable=protected-access import re import shutil +import sys import tempfile import unittest from unittest import mock import configobj +import pytest from certbot import configuration from certbot import errors @@ -710,4 +712,4 @@ class GetCertnameTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/cli_test.py b/certbot/tests/cli_test.py index 0b2108b73..53eb2a5bc 100644 --- a/certbot/tests/cli_test.py +++ b/certbot/tests/cli_test.py @@ -3,10 +3,13 @@ import argparse import copy from importlib import reload as reload_module import io +import sys import tempfile import unittest from unittest import mock +import pytest + from acme import challenges from certbot import errors from certbot._internal import cli @@ -521,4 +524,4 @@ def _call_set_by_cli(var, args, verb): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/client_test.py b/certbot/tests/client_test.py index 7b29d26ca..405858e97 100644 --- a/certbot/tests/client_test.py +++ b/certbot/tests/client_test.py @@ -3,12 +3,14 @@ import contextlib import datetime import platform import shutil +import sys import tempfile import unittest from unittest import mock from unittest.mock import MagicMock from josepy import interfaces +import pytest from certbot import errors from certbot import util @@ -979,4 +981,4 @@ class RollbackTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/compat/filesystem_test.py b/certbot/tests/compat/filesystem_test.py index fd4cb9cde..a634e34ad 100644 --- a/certbot/tests/compat/filesystem_test.py +++ b/certbot/tests/compat/filesystem_test.py @@ -1,9 +1,12 @@ """Tests for certbot.compat.filesystem""" import contextlib import errno +import sys import unittest from unittest import mock +import pytest + from certbot import util from certbot._internal import lock from certbot.compat import filesystem @@ -679,4 +682,4 @@ def _create_probe(tempdir, name='probe'): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/compat/misc_test.py b/certbot/tests/compat/misc_test.py index 5cb8167b6..5668e0718 100644 --- a/certbot/tests/compat/misc_test.py +++ b/certbot/tests/compat/misc_test.py @@ -1,7 +1,10 @@ """Tests for certbot.compat.misc""" +import sys import unittest from unittest import mock +import pytest + from certbot.compat import os @@ -43,4 +46,4 @@ class ExecuteStatusTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/compat/os_test.py b/certbot/tests/compat/os_test.py index 2fe23f700..844492678 100644 --- a/certbot/tests/compat/os_test.py +++ b/certbot/tests/compat/os_test.py @@ -1,6 +1,9 @@ """Unit test for os module.""" +import sys import unittest +import pytest + from certbot.compat import os @@ -17,4 +20,4 @@ class OsTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/configuration_test.py b/certbot/tests/configuration_test.py index 22060a688..1d860ea0d 100644 --- a/certbot/tests/configuration_test.py +++ b/certbot/tests/configuration_test.py @@ -1,8 +1,11 @@ """Tests for certbot.configuration.""" +import sys import unittest from unittest import mock import warnings +import pytest + from certbot import errors from certbot._internal import constants from certbot.compat import misc @@ -163,4 +166,4 @@ class NamespaceConfigTest(test_util.ConfigTestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/crypto_util_test.py b/certbot/tests/crypto_util_test.py index 46dc86436..141588d81 100644 --- a/certbot/tests/crypto_util_test.py +++ b/certbot/tests/crypto_util_test.py @@ -1,9 +1,11 @@ """Tests for certbot.crypto_util.""" import logging +import sys import unittest from unittest import mock import OpenSSL +import pytest from certbot import errors from certbot import util @@ -525,4 +527,4 @@ class FindChainWithIssuerTest(unittest.TestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/display/completer_test.py b/certbot/tests/display/completer_test.py index 73722151a..e4f2d758e 100644 --- a/certbot/tests/display/completer_test.py +++ b/certbot/tests/display/completer_test.py @@ -1,19 +1,22 @@ """Test certbot._internal.display.completer.""" +from importlib import reload as reload_module +import string +import sys from typing import List +import unittest +from unittest import mock + +import pytest + +from certbot.compat import filesystem +from certbot.compat import os +import certbot.tests.util as test_util try: import readline # pylint: disable=import-error except ImportError: import certbot._internal.display.dummy_readline as readline # type: ignore -from importlib import reload as reload_module -import string -import sys -import unittest -from unittest import mock -from certbot.compat import filesystem -from certbot.compat import os -import certbot.tests.util as test_util class CompleterTest(test_util.TempDirTestCase): @@ -104,4 +107,4 @@ def enable_tab_completion(unused_command): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/display/internal_util_test.py b/certbot/tests/display/internal_util_test.py index b29396c41..61ee8d281 100644 --- a/certbot/tests/display/internal_util_test.py +++ b/certbot/tests/display/internal_util_test.py @@ -1,10 +1,13 @@ """Test :mod:`certbot._internal.display.util`.""" import io import socket +import sys import tempfile import unittest from unittest import mock +import pytest + from acme import messages as acme_messages from certbot import errors @@ -146,4 +149,4 @@ class DescribeACMEErrorTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/display/obj_test.py b/certbot/tests/display/obj_test.py index 4da2c3b3b..d180d8059 100644 --- a/certbot/tests/display/obj_test.py +++ b/certbot/tests/display/obj_test.py @@ -1,7 +1,10 @@ """Test :mod:`certbot._internal.display.obj`.""" +import sys import unittest from unittest import mock +import pytest + from certbot import errors from certbot._internal.display import obj as display_obj from certbot.display import util as display_util @@ -330,4 +333,4 @@ class NoninteractiveDisplayTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/display/ops_test.py b/certbot/tests/display/ops_test.py index 69c7440be..ded89b245 100644 --- a/certbot/tests/display/ops_test.py +++ b/certbot/tests/display/ops_test.py @@ -5,6 +5,7 @@ import unittest from unittest import mock import josepy as jose +import pytest from acme import messages from certbot import errors @@ -517,4 +518,4 @@ class ReportExecutedCommand(unittest.TestCase): self.assertEqual(mock_notify.call_count, 0) if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/display/util_test.py b/certbot/tests/display/util_test.py index 7eb45653c..4ae2d7c00 100644 --- a/certbot/tests/display/util_test.py +++ b/certbot/tests/display/util_test.py @@ -1,10 +1,13 @@ """Test :mod:`certbot.display.util`.""" import io import socket +import sys import tempfile import unittest from unittest import mock +import pytest + from certbot import errors import certbot.tests.util as test_util @@ -95,4 +98,4 @@ class DirectorySelectTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/eff_test.py b/certbot/tests/eff_test.py index a87ca2204..3a13e2ff1 100644 --- a/certbot/tests/eff_test.py +++ b/certbot/tests/eff_test.py @@ -1,9 +1,11 @@ """Tests for certbot._internal.eff.""" import datetime +import sys import unittest from unittest import mock import josepy +import pytest import pytz import requests @@ -179,4 +181,4 @@ class SubscribeTest(unittest.TestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/error_handler_test.py b/certbot/tests/error_handler_test.py index d6d506956..799350f8c 100644 --- a/certbot/tests/error_handler_test.py +++ b/certbot/tests/error_handler_test.py @@ -8,6 +8,8 @@ from typing import Union import unittest from unittest import mock +import pytest + from certbot.compat import os @@ -150,4 +152,4 @@ class ExitHandlerTest(ErrorHandlerTest): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/errors_test.py b/certbot/tests/errors_test.py index d05f2b43e..b9decfd68 100644 --- a/certbot/tests/errors_test.py +++ b/certbot/tests/errors_test.py @@ -1,7 +1,10 @@ """Tests for certbot.errors.""" +import sys import unittest from unittest import mock +import pytest + from acme import messages from certbot import achallenges from certbot.tests import acme_util @@ -52,4 +55,4 @@ class StandaloneBindErrorTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/helpful_test.py b/certbot/tests/helpful_test.py index 2965f582a..6a60362d0 100644 --- a/certbot/tests/helpful_test.py +++ b/certbot/tests/helpful_test.py @@ -1,7 +1,10 @@ """Tests for certbot.helpful_parser""" +import sys import unittest from unittest import mock +import pytest + from certbot import errors from certbot._internal import constants from certbot._internal.cli import _DomainsAction @@ -202,4 +205,4 @@ class TestAddDeprecatedArgument(unittest.TestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/hook_test.py b/certbot/tests/hook_test.py index 8cd8e6631..4260a0b30 100644 --- a/certbot/tests/hook_test.py +++ b/certbot/tests/hook_test.py @@ -1,7 +1,10 @@ """Tests for certbot._internal.hooks.""" +import sys import unittest from unittest import mock +import pytest + from certbot import errors from certbot import util from certbot.compat import filesystem @@ -459,4 +462,4 @@ def create_hook(file_path): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/lock_test.py b/certbot/tests/lock_test.py index 1e7525782..fd36bb225 100644 --- a/certbot/tests/lock_test.py +++ b/certbot/tests/lock_test.py @@ -1,9 +1,12 @@ """Tests for certbot._internal.lock.""" import functools import multiprocessing +import sys import unittest from unittest import mock +import pytest + from certbot import errors from certbot.compat import os from certbot.tests import util as test_util @@ -138,4 +141,4 @@ class LockFileTest(test_util.TempDirTestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/log_test.py b/certbot/tests/log_test.py index bee33261c..4aaa9bcbd 100644 --- a/certbot/tests/log_test.py +++ b/certbot/tests/log_test.py @@ -8,6 +8,8 @@ from typing import Optional import unittest from unittest import mock +import pytest + from acme import messages from certbot import errors from certbot import util @@ -433,4 +435,4 @@ class ExitWithAdviceTest(test_util.TempDirTestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index 0b24ff30d..e8230d87e 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -16,6 +16,7 @@ from unittest import mock import configobj import josepy as jose +import pytest import pytz from acme.messages import Error as acme_error @@ -2469,4 +2470,4 @@ class ShowAccountTest(test_util.ConfigTestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/ocsp_test.py b/certbot/tests/ocsp_test.py index ebb98c343..4f7a39956 100644 --- a/certbot/tests/ocsp_test.py +++ b/certbot/tests/ocsp_test.py @@ -3,6 +3,7 @@ import contextlib from datetime import datetime from datetime import timedelta +import sys import unittest from unittest import mock @@ -12,6 +13,7 @@ from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.x509 import ocsp as ocsp_lib +import pytest import pytz from certbot import errors @@ -386,4 +388,4 @@ revoked if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/plugins/common_test.py b/certbot/tests/plugins/common_test.py index 215faaea3..00f9f1c26 100644 --- a/certbot/tests/plugins/common_test.py +++ b/certbot/tests/plugins/common_test.py @@ -1,10 +1,12 @@ """Tests for certbot.plugins.common.""" import functools import shutil +import sys import unittest from unittest import mock import josepy as jose +import pytest from acme import challenges from certbot import achallenges @@ -366,4 +368,4 @@ class InstallVersionControlledFileTest(test_util.TempDirTestCase): self.assertIs(mock_logger.warning.called, False) if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/plugins/disco_test.py b/certbot/tests/plugins/disco_test.py index dfd9d0c7b..a3b69ff0c 100644 --- a/certbot/tests/plugins/disco_test.py +++ b/certbot/tests/plugins/disco_test.py @@ -1,11 +1,13 @@ """Tests for certbot._internal.plugins.disco.""" import functools import string +import sys from typing import List import unittest from unittest import mock import pkg_resources +import pytest from certbot import errors from certbot import interfaces @@ -271,4 +273,4 @@ class PluginsRegistryTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/plugins/dns_common_lexicon_test.py b/certbot/tests/plugins/dns_common_lexicon_test.py index 4634c2057..53bcb1a0d 100644 --- a/certbot/tests/plugins/dns_common_lexicon_test.py +++ b/certbot/tests/plugins/dns_common_lexicon_test.py @@ -1,8 +1,11 @@ """Tests for certbot.plugins.dns_common_lexicon.""" +import sys import unittest from unittest import mock +import pytest + from certbot.plugins import dns_common_lexicon from certbot.plugins import dns_test_common_lexicon @@ -23,4 +26,4 @@ class LexiconClientTest(unittest.TestCase, dns_test_common_lexicon.BaseLexiconCl if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/plugins/dns_common_test.py b/certbot/tests/plugins/dns_common_test.py index 97bc5dea6..19a359541 100644 --- a/certbot/tests/plugins/dns_common_test.py +++ b/certbot/tests/plugins/dns_common_test.py @@ -2,9 +2,12 @@ import collections import logging +import sys import unittest from unittest import mock +import pytest + from certbot import errors from certbot import util from certbot.compat import os @@ -233,4 +236,4 @@ class DomainNameGuessTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/plugins/enhancements_test.py b/certbot/tests/plugins/enhancements_test.py index 903d3e095..917b74db8 100644 --- a/certbot/tests/plugins/enhancements_test.py +++ b/certbot/tests/plugins/enhancements_test.py @@ -1,7 +1,10 @@ """Tests for new style enhancements""" +import sys import unittest from unittest import mock +import pytest + from certbot._internal.plugins import null from certbot.plugins import enhancements import certbot.tests.util as test_util @@ -59,4 +62,4 @@ class EnhancementTest(test_util.ConfigTestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/plugins/manual_test.py b/certbot/tests/plugins/manual_test.py index a5dc69c32..19064bc00 100644 --- a/certbot/tests/plugins/manual_test.py +++ b/certbot/tests/plugins/manual_test.py @@ -4,6 +4,8 @@ import textwrap import unittest from unittest import mock +import pytest + from acme import challenges from certbot import errors from certbot.compat import filesystem @@ -159,4 +161,4 @@ class AuthenticatorTest(test_util.TempDirTestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/plugins/null_test.py b/certbot/tests/plugins/null_test.py index ce3440e5b..64a5b0709 100644 --- a/certbot/tests/plugins/null_test.py +++ b/certbot/tests/plugins/null_test.py @@ -1,7 +1,10 @@ """Tests for certbot._internal.plugins.null.""" +import sys import unittest from unittest import mock +import pytest + class InstallerTest(unittest.TestCase): """Tests for certbot._internal.plugins.null.Installer.""" @@ -17,4 +20,4 @@ class InstallerTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/plugins/selection_test.py b/certbot/tests/plugins/selection_test.py index 6aed9ec8d..272cdb484 100644 --- a/certbot/tests/plugins/selection_test.py +++ b/certbot/tests/plugins/selection_test.py @@ -4,6 +4,8 @@ from typing import List import unittest from unittest import mock +import pytest + from certbot import errors from certbot import interfaces from certbot._internal.display import obj as display_obj @@ -261,4 +263,4 @@ class TestChooseConfiguratorPlugins(unittest.TestCase): self.assertEqual(auth.name, "apache") if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/plugins/standalone_test.py b/certbot/tests/plugins/standalone_test.py index 39454570e..6e173ed79 100644 --- a/certbot/tests/plugins/standalone_test.py +++ b/certbot/tests/plugins/standalone_test.py @@ -1,6 +1,7 @@ """Tests for certbot._internal.plugins.standalone.""" import errno import socket +import sys from typing import Dict from typing import Set from typing import Tuple @@ -9,6 +10,7 @@ from unittest import mock import josepy as jose import OpenSSL.crypto +import pytest from acme import challenges from acme import standalone as acme_standalone @@ -185,4 +187,4 @@ class AuthenticatorTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/plugins/storage_test.py b/certbot/tests/plugins/storage_test.py index 82b0aff65..ae4b575e0 100644 --- a/certbot/tests/plugins/storage_test.py +++ b/certbot/tests/plugins/storage_test.py @@ -1,11 +1,14 @@ """Tests for certbot.plugins.storage.PluginStorage""" import json +import sys from typing import Iterable from typing import List from typing import Optional import unittest from unittest import mock +import pytest + from certbot import errors from certbot.compat import filesystem from certbot.compat import os @@ -117,4 +120,4 @@ class PluginStorageTest(test_util.ConfigTestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/plugins/util_test.py b/certbot/tests/plugins/util_test.py index faac01165..eabfe5fa3 100644 --- a/certbot/tests/plugins/util_test.py +++ b/certbot/tests/plugins/util_test.py @@ -1,7 +1,10 @@ """Tests for certbot.plugins.util.""" +import sys import unittest from unittest import mock +import pytest + from certbot.compat import os @@ -41,4 +44,4 @@ class PathSurgeryTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/plugins/webroot_test.py b/certbot/tests/plugins/webroot_test.py index 4bc198074..210be36e6 100644 --- a/certbot/tests/plugins/webroot_test.py +++ b/certbot/tests/plugins/webroot_test.py @@ -6,11 +6,13 @@ import argparse import errno import json import shutil +import sys import tempfile import unittest from unittest import mock import josepy as jose +import pytest from acme import challenges from certbot import achallenges @@ -360,4 +362,4 @@ class WebrootActionTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/renewal_test.py b/certbot/tests/renewal_test.py index 4d337830e..93036fd6c 100644 --- a/certbot/tests/renewal_test.py +++ b/certbot/tests/renewal_test.py @@ -1,8 +1,11 @@ """Tests for certbot._internal.renewal""" import copy +import sys import unittest from unittest import mock +import pytest + from acme import challenges from certbot import configuration from certbot import errors @@ -305,4 +308,4 @@ class DescribeResultsTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/renewupdater_test.py b/certbot/tests/renewupdater_test.py index 30a7b0f46..c2e32f867 100644 --- a/certbot/tests/renewupdater_test.py +++ b/certbot/tests/renewupdater_test.py @@ -1,7 +1,10 @@ """Tests for renewal updater interfaces""" +import sys import unittest from unittest import mock +import pytest + from certbot import interfaces from certbot._internal import main from certbot._internal import updater @@ -120,4 +123,4 @@ class RenewUpdaterTest(test_util.ConfigTestCase): if __name__ == '__main__': - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/reverter_test.py b/certbot/tests/reverter_test.py index 2fb28862d..7a70a4313 100644 --- a/certbot/tests/reverter_test.py +++ b/certbot/tests/reverter_test.py @@ -2,10 +2,13 @@ import csv import logging import shutil +import sys import tempfile import unittest from unittest import mock +import pytest + from certbot import errors from certbot.compat import os from certbot.tests import util as test_util @@ -454,4 +457,4 @@ def update_file(filename, string): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/storage_test.py b/certbot/tests/storage_test.py index 13c2be0a5..4cad7899d 100644 --- a/certbot/tests/storage_test.py +++ b/certbot/tests/storage_test.py @@ -3,10 +3,12 @@ import datetime import shutil import stat +import sys import unittest from unittest import mock import configobj +import pytest import pytz import certbot @@ -967,4 +969,4 @@ class CertPathForCertNameTest(BaseRenewableCertTest): self.assertRaises(errors.CertStorageError, self._call, self.config, 'fake-example.org') if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/util_test.py b/certbot/tests/util_test.py index 0904c028f..e02638037 100644 --- a/certbot/tests/util_test.py +++ b/certbot/tests/util_test.py @@ -7,6 +7,8 @@ import sys import unittest from unittest import mock +import pytest + from certbot import errors from certbot.compat import filesystem from certbot.compat import os @@ -654,4 +656,4 @@ class ParseLooseVersionTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() # pragma: no cover + sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover From 64800c2b1f0db4e11459c4834c1a97fcb594629b Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 14 Feb 2023 08:51:17 -0800 Subject: [PATCH 36/57] disable stale for PRs --- .github/workflows/stale.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index fe9b55ec9..6e6a227d3 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -17,9 +17,15 @@ jobs: # Idle number of days before marking issues stale days-before-issue-stale: 365 + # Never mark PRs as stale + days-before-pr-stale: -1 + # Idle number of days before closing stale issues days-before-issue-close: 30 + # Never close PRs as stale + days-before-pr-close: -1 + # Ignore issues with an assignee exempt-all-issue-assignees: true From 1da113d7d60829c441ccdeec40347d4d9821403a Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 14 Feb 2023 08:55:07 -0800 Subject: [PATCH 37/57] tweak comment --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 6e6a227d3..d8e227c77 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -23,7 +23,7 @@ jobs: # Idle number of days before closing stale issues days-before-issue-close: 30 - # Never close PRs as stale + # Never close PRs days-before-pr-close: -1 # Ignore issues with an assignee From 1fe2d671cb401808995b66db165ef62d9e7ca94f Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Tue, 14 Feb 2023 12:42:21 -0800 Subject: [PATCH 38/57] Update changelog for 2.3.0 release --- certbot/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index a3b8b23f5..b742b5cd2 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -2,7 +2,7 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). -## 2.3.0 - master +## 2.3.0 - 2023-02-14 ### Added From d4b2d3202bb7cb58d3e24bcc95b104b102600005 Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Tue, 14 Feb 2023 12:44:31 -0800 Subject: [PATCH 39/57] Release 2.3.0 --- acme/setup.py | 2 +- certbot-apache/setup.py | 2 +- certbot-compatibility-test/setup.py | 2 +- certbot-dns-cloudflare/setup.py | 2 +- certbot-dns-digitalocean/setup.py | 2 +- certbot-dns-dnsimple/setup.py | 2 +- certbot-dns-dnsmadeeasy/setup.py | 2 +- certbot-dns-gehirn/setup.py | 2 +- certbot-dns-google/setup.py | 2 +- certbot-dns-linode/setup.py | 2 +- certbot-dns-luadns/setup.py | 2 +- certbot-dns-nsone/setup.py | 2 +- certbot-dns-ovh/setup.py | 2 +- certbot-dns-rfc2136/setup.py | 2 +- certbot-dns-route53/setup.py | 2 +- certbot-dns-sakuracloud/setup.py | 2 +- certbot-nginx/setup.py | 2 +- certbot/certbot/__init__.py | 2 +- certbot/docs/cli-help.txt | 50 ++++++++++++++++++++--------- 19 files changed, 53 insertions(+), 33 deletions(-) diff --git a/acme/setup.py b/acme/setup.py index 1dbdc1291..4ff19fc86 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -3,7 +3,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ 'cryptography>=2.5.0', diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index ab545be03..0fa966c15 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -1,7 +1,7 @@ from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ # We specify the minimum acme and certbot version as the current plugin diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index 2b8226d6e..5548cd72f 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -1,7 +1,7 @@ from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ 'certbot', diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index 3ac78a942..e251e52d8 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ 'cloudflare>=1.5.1', diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index ca1b1612e..718115892 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ 'python-digitalocean>=1.11', # 1.15.0 or newer is recommended for TTL support diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index 5760b6381..2b7ebb799 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ # This version of lexicon is required to address the problem described in diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index 103b8c3e9..663f1b182 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ 'dns-lexicon>=3.2.1', diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 77cd937b3..4bbe47ed2 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ 'dns-lexicon>=3.2.1', diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index eb4152456..b16a16ebd 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ 'google-api-python-client>=1.5.5', diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index 3ff9ad5a0..0bbd897dc 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ 'dns-lexicon>=3.2.1', diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index 729e9950c..e4197fa37 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ 'dns-lexicon>=3.2.1', diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index 039cbb180..b91e0207a 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ 'dns-lexicon>=3.2.1', diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index 8748f6293..612e549ca 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ 'dns-lexicon>=3.2.1', diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index 476c8a4ab..8282ca4fb 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ 'dnspython>=1.15.0', diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index 596146d05..40bd21545 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ 'boto3>=1.15.15', diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index 464380ccc..6064ce852 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ 'dns-lexicon>=3.2.1', diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index a2beec1d6..9963a75e2 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -1,7 +1,7 @@ from setuptools import find_packages from setuptools import setup -version = '2.3.0.dev0' +version = '2.3.0' install_requires = [ # We specify the minimum acme and certbot version as the current plugin diff --git a/certbot/certbot/__init__.py b/certbot/certbot/__init__.py index 331332bb7..7da96a76d 100644 --- a/certbot/certbot/__init__.py +++ b/certbot/certbot/__init__.py @@ -1,3 +1,3 @@ """Certbot client.""" # version number like 1.2.3a0, must have at least 2 parts, like 1.2 -__version__ = '2.3.0.dev0' +__version__ = '2.3.0' diff --git a/certbot/docs/cli-help.txt b/certbot/docs/cli-help.txt index dd270e6eb..d2eb17da2 100644 --- a/certbot/docs/cli-help.txt +++ b/certbot/docs/cli-help.txt @@ -26,6 +26,7 @@ manage certificates: certificates Display information about certificates you have from Certbot revoke Revoke a certificate (supply --cert-name or --cert-path) delete Delete a certificate (supply --cert-name) + reconfigure Update a certificate's configuration (supply --cert-name) manage your account: register Create an ACME account @@ -35,7 +36,7 @@ manage your account: --agree-tos Agree to the ACME server's Subscriber Agreement -m EMAIL Email address for important account notifications -optional arguments: +options: -h, --help show this help message and exit -c CONFIG_FILE, --config CONFIG_FILE path to config file (default: /etc/letsencrypt/cli.ini @@ -58,18 +59,15 @@ optional arguments: it's not being run in a terminal. This flag cannot be used with the renew subcommand. (default: False) -d DOMAIN, --domains DOMAIN, --domain DOMAIN - Domain names to apply. For multiple domains you can + Domain names to include. For multiple domains you can use multiple -d flags or enter a comma separated list - of domains as a parameter. The first domain provided - will be the subject CN of the certificate, and all - domains will be Subject Alternative Names on the - certificate. The first domain will also be used in - some software user interfaces and as the file paths - for the certificate and related material unless - otherwise specified or you already have a certificate - with the same name. In the case of a name collision it - will append a number like 0001 to the file path name. - (default: Ask) + of domains as a parameter. All domains will be + included as Subject Alternative Names on the + certificate. The first domain will be used as the + certificate name, unless otherwise specified or if you + already have a certificate with the same name. In the + case of a name conflict, a number like -0001 will be + appended to the certificate name. (default: Ask) --eab-kid EAB_KID Key Identifier for External Account Binding (default: None) --eab-hmac-key EAB_HMAC_KEY @@ -126,7 +124,7 @@ optional arguments: case, and to know when to deprecate support for past Python versions and flags. If you wish to hide this information from the Let's Encrypt server, set this to - "". (default: CertbotACMEClient/2.2.0 (certbot; + "". (default: CertbotACMEClient/2.3.0 (certbot; OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY (SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel). The flags encoded in the user agent are: --duplicate, @@ -229,6 +227,17 @@ security: testing: The following flags are meant for testing and integration purposes only. + --run-deploy-hooks When performing a test run using `--dry-run` or + `reconfigure`, run any applicable deploy hooks. This + includes hooks set on the command line, saved in the + certificate's renewal configuration file, or present + in the renewal-hooks directory. To exclude directory + hooks, use --no-directory-hooks. The hook(s) will only + be run if the dry run succeeds, and will use the + current active certificate, not the temporary test + certificate acquired during the dry run. This flag is + recommended when modifying the deploy hook using + `reconfigure`. (default: False) --test-cert, --staging Use the staging server to obtain or revoke test (invalid) certificates; equivalent to --server @@ -288,6 +297,8 @@ manage: --cert-name update_symlinks Recreate symlinks in your /etc/letsencrypt/live/ directory + reconfigure Update renewal configuration for a certificate + specified by --cert-name run: Options for obtaining & installing certificates @@ -432,6 +443,9 @@ enhance: show_account: Options useful for the "show_account" subcommand: +reconfigure: + Common options that may be updated with the "reconfigure" subcommand: + plugins: Plugin Selection: Certbot client supports an extensible plugins architecture. See 'certbot plugins' for a list of all installed plugins @@ -707,10 +721,16 @@ null: Null Installer standalone: - Spin up a temporary webserver + Runs an HTTP server locally which serves the necessary validation files + under the /.well-known/acme-challenge/ request path. Suitable if there is + no HTTP server already running. HTTP challenge only (wildcards not + supported). webroot: - Place files in webroot directory + Saves the necessary validation files to a .well-known/acme-challenge/ + directory within the nominated webroot path. A seperate HTTP server must + be running and serving files from the webroot path. HTTP challenge only + (wildcards not supported). --webroot-path WEBROOT_PATH, -w WEBROOT_PATH public_html / webroot path. This can be specified From 5d34a4d982a1046e6794143ed9a63f3e05dd082b Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Tue, 14 Feb 2023 12:44:32 -0800 Subject: [PATCH 40/57] Add contents to certbot/CHANGELOG.md for next version --- certbot/CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index b742b5cd2..87ead3bab 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -2,6 +2,22 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). +## 2.4.0 - master + +### Added + +* + +### Changed + +* + +### Fixed + +* + +More details about these changes can be found on our GitHub repo. + ## 2.3.0 - 2023-02-14 ### Added From 941119f05bedf94c2f359a802c73cac702ce8e46 Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Tue, 14 Feb 2023 12:44:32 -0800 Subject: [PATCH 41/57] Bump version to 2.4.0 --- acme/docs/jws-help.txt | 2 +- acme/setup.py | 2 +- certbot-apache/setup.py | 2 +- certbot-compatibility-test/setup.py | 2 +- certbot-dns-cloudflare/setup.py | 2 +- certbot-dns-digitalocean/setup.py | 2 +- certbot-dns-dnsimple/setup.py | 2 +- certbot-dns-dnsmadeeasy/setup.py | 2 +- certbot-dns-gehirn/setup.py | 2 +- certbot-dns-google/setup.py | 2 +- certbot-dns-linode/setup.py | 2 +- certbot-dns-luadns/setup.py | 2 +- certbot-dns-nsone/setup.py | 2 +- certbot-dns-ovh/setup.py | 2 +- certbot-dns-rfc2136/setup.py | 2 +- certbot-dns-route53/setup.py | 2 +- certbot-dns-sakuracloud/setup.py | 2 +- certbot-nginx/setup.py | 2 +- certbot/certbot/__init__.py | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/acme/docs/jws-help.txt b/acme/docs/jws-help.txt index 34cf5ce23..bfd16dff4 100644 --- a/acme/docs/jws-help.txt +++ b/acme/docs/jws-help.txt @@ -3,6 +3,6 @@ usage: jws [-h] [--compact] {sign,verify} ... positional arguments: {sign,verify} -optional arguments: +options: -h, --help show this help message and exit --compact diff --git a/acme/setup.py b/acme/setup.py index 4ff19fc86..577a43be3 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -3,7 +3,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ 'cryptography>=2.5.0', diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index 0fa966c15..7665a0a30 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -1,7 +1,7 @@ from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ # We specify the minimum acme and certbot version as the current plugin diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index 5548cd72f..90f7ecd2d 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -1,7 +1,7 @@ from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ 'certbot', diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index e251e52d8..df074b8f4 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ 'cloudflare>=1.5.1', diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index 718115892..c1f637a73 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ 'python-digitalocean>=1.11', # 1.15.0 or newer is recommended for TTL support diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index 2b7ebb799..e17de6876 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ # This version of lexicon is required to address the problem described in diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index 663f1b182..e1482678c 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ 'dns-lexicon>=3.2.1', diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 4bbe47ed2..773480210 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ 'dns-lexicon>=3.2.1', diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index b16a16ebd..58e823f13 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ 'google-api-python-client>=1.5.5', diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index 0bbd897dc..e77f17968 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ 'dns-lexicon>=3.2.1', diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index e4197fa37..5abeaea3b 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ 'dns-lexicon>=3.2.1', diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index b91e0207a..04eb47cd3 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ 'dns-lexicon>=3.2.1', diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index 612e549ca..8f7bbcfd8 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ 'dns-lexicon>=3.2.1', diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index 8282ca4fb..57f1466e2 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ 'dnspython>=1.15.0', diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index 40bd21545..0d9ece96e 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ 'boto3>=1.15.15', diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index 6064ce852..272ae827e 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ 'dns-lexicon>=3.2.1', diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index 9963a75e2..8adfd2947 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -1,7 +1,7 @@ from setuptools import find_packages from setuptools import setup -version = '2.3.0' +version = '2.4.0.dev0' install_requires = [ # We specify the minimum acme and certbot version as the current plugin diff --git a/certbot/certbot/__init__.py b/certbot/certbot/__init__.py index 7da96a76d..dbe6c3787 100644 --- a/certbot/certbot/__init__.py +++ b/certbot/certbot/__init__.py @@ -1,3 +1,3 @@ """Certbot client.""" # version number like 1.2.3a0, must have at least 2 parts, like 1.2 -__version__ = '2.3.0' +__version__ = '2.4.0.dev0' From 1b904b62c9e82f4e457709c7534657eceb15e98d Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Tue, 14 Feb 2023 15:13:13 -0800 Subject: [PATCH 42/57] Enable stale issue tracker (#9580) --- .github/workflows/stale.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index d8e227c77..327930d70 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -11,9 +11,6 @@ jobs: steps: - uses: actions/stale@v6 with: - # REMOVEME: dry run to see if this works - debug-only: true - # Idle number of days before marking issues stale days-before-issue-stale: 365 From a3c9371dc5d3f51b1382da84acc3bb42bea8426b Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 15 Feb 2023 21:02:02 -0800 Subject: [PATCH 43/57] Use pytest assertions (#9585) * run unittest2pytest The command used here was `unittest2pytest -nw acme/tests certbot*/tests`. * fix with pytest.raises * add parens to fix refactoring * <= not < --- acme/tests/challenges_test.py | 159 +++-- acme/tests/client_test.py | 245 ++++--- acme/tests/crypto_util_test.py | 123 ++-- acme/tests/errors_test.py | 14 +- acme/tests/fields_test.py | 23 +- acme/tests/jose_test.py | 8 +- acme/tests/jws_test.py | 20 +- acme/tests/messages_test.py | 170 +++-- acme/tests/standalone_test.py | 36 +- acme/tests/util_test.py | 6 +- certbot-apache/tests/augeasnode_test.py | 127 ++-- certbot-apache/tests/autohsts_test.py | 65 +- certbot-apache/tests/centos_test.py | 85 +-- certbot-apache/tests/complex_parsing_test.py | 44 +- .../tests/configurator_reverter_test.py | 21 +- certbot-apache/tests/configurator_test.py | 637 +++++++++--------- certbot-apache/tests/debian_test.py | 67 +- certbot-apache/tests/display_ops_test.py | 22 +- certbot-apache/tests/dualnode_test.py | 105 +-- certbot-apache/tests/entrypoint_test.py | 12 +- certbot-apache/tests/fedora_test.py | 50 +- certbot-apache/tests/gentoo_test.py | 20 +- certbot-apache/tests/http_01_test.py | 44 +- certbot-apache/tests/obj_test.py | 97 ++- certbot-apache/tests/parser_test.py | 98 ++- .../tests/parsernode_configurator_test.py | 4 +- certbot-apache/tests/parsernode_util_test.py | 36 +- .../tests/dns_cloudflare_test.py | 102 ++- .../tests/dns_digitalocean_test.py | 25 +- certbot-dns-google/tests/dns_google_test.py | 67 +- certbot-dns-linode/tests/dns_linode_test.py | 15 +- certbot-dns-rfc2136/tests/dns_rfc2136_test.py | 64 +- certbot-dns-route53/tests/dns_route53_test.py | 48 +- certbot-nginx/tests/configurator_test.py | 362 +++++----- certbot-nginx/tests/display_ops_test.py | 12 +- certbot-nginx/tests/http_01_test.py | 36 +- certbot-nginx/tests/nginxparser_test.py | 191 +++--- certbot-nginx/tests/obj_test.py | 121 ++-- certbot-nginx/tests/parser_obj_test.py | 155 +++-- certbot-nginx/tests/parser_test.py | 166 +++-- certbot/tests/account_test.py | 147 ++-- certbot/tests/auth_handler_test.py | 215 +++--- certbot/tests/cert_manager_test.py | 212 +++--- certbot/tests/cli_test.py | 287 ++++---- certbot/tests/client_test.py | 265 ++++---- certbot/tests/compat/filesystem_test.py | 165 +++-- certbot/tests/compat/misc_test.py | 6 +- certbot/tests/compat/os_test.py | 6 +- certbot/tests/configuration_test.py | 112 ++- certbot/tests/crypto_util_test.py | 187 +++-- certbot/tests/display/completer_test.py | 12 +- certbot/tests/display/internal_util_test.py | 47 +- certbot/tests/display/obj_test.py | 144 ++-- certbot/tests/display/ops_test.py | 146 ++-- certbot/tests/eff_test.py | 52 +- certbot/tests/error_handler_test.py | 12 +- certbot/tests/errors_test.py | 16 +- certbot/tests/helpful_test.py | 63 +- certbot/tests/hook_test.py | 62 +- certbot/tests/lock_test.py | 20 +- certbot/tests/log_test.py | 76 +-- certbot/tests/main_test.py | 519 +++++++------- certbot/tests/ocsp_test.py | 112 +-- certbot/tests/plugins/common_test.py | 163 ++--- certbot/tests/plugins/disco_test.py | 154 ++--- certbot/tests/plugins/dns_common_test.py | 48 +- certbot/tests/plugins/enhancements_test.py | 24 +- certbot/tests/plugins/manual_test.py | 90 ++- certbot/tests/plugins/null_test.py | 6 +- certbot/tests/plugins/selection_test.py | 66 +- certbot/tests/plugins/standalone_test.py | 60 +- certbot/tests/plugins/storage_test.py | 53 +- certbot/tests/plugins/util_test.py | 23 +- certbot/tests/plugins/webroot_test.py | 112 +-- certbot/tests/renewal_test.py | 41 +- certbot/tests/renewupdater_test.py | 34 +- certbot/tests/reverter_test.py | 147 ++-- certbot/tests/storage_test.py | 467 +++++++------ certbot/tests/util_test.py | 220 +++--- 79 files changed, 4060 insertions(+), 4233 deletions(-) diff --git a/acme/tests/challenges_test.py b/acme/tests/challenges_test.py index 000451f78..1febaff54 100644 --- a/acme/tests/challenges_test.py +++ b/acme/tests/challenges_test.py @@ -23,7 +23,7 @@ class ChallengeTest(unittest.TestCase): from acme.challenges import Challenge from acme.challenges import UnrecognizedChallenge chall = UnrecognizedChallenge({"type": "foo"}) - self.assertEqual(chall, Challenge.from_json(chall.jobj)) + assert chall == Challenge.from_json(chall.jobj) class UnrecognizedChallengeTest(unittest.TestCase): @@ -34,12 +34,11 @@ class UnrecognizedChallengeTest(unittest.TestCase): self.chall = UnrecognizedChallenge(self.jobj) def test_to_partial_json(self): - self.assertEqual(self.jobj, self.chall.to_partial_json()) + assert self.jobj == self.chall.to_partial_json() def test_from_json(self): from acme.challenges import UnrecognizedChallenge - self.assertEqual( - self.chall, UnrecognizedChallenge.from_json(self.jobj)) + assert self.chall == UnrecognizedChallenge.from_json(self.jobj) class KeyAuthorizationChallengeResponseTest(unittest.TestCase): @@ -55,26 +54,26 @@ class KeyAuthorizationChallengeResponseTest(unittest.TestCase): from acme.challenges import KeyAuthorizationChallengeResponse response = KeyAuthorizationChallengeResponse( key_authorization='foo.oKGqedy-b-acd5eoybm2f-NVFxvyOoET5CNy3xnv8WY') - self.assertTrue(response.verify(self.chall, KEY.public_key())) + assert response.verify(self.chall, KEY.public_key()) def test_verify_wrong_token(self): from acme.challenges import KeyAuthorizationChallengeResponse response = KeyAuthorizationChallengeResponse( key_authorization='bar.oKGqedy-b-acd5eoybm2f-NVFxvyOoET5CNy3xnv8WY') - self.assertFalse(response.verify(self.chall, KEY.public_key())) + assert not response.verify(self.chall, KEY.public_key()) def test_verify_wrong_thumbprint(self): from acme.challenges import KeyAuthorizationChallengeResponse response = KeyAuthorizationChallengeResponse( key_authorization='foo.oKGqedy-b-acd5eoybm2f-NVFxv') - self.assertFalse(response.verify(self.chall, KEY.public_key())) + assert not response.verify(self.chall, KEY.public_key()) def test_verify_wrong_form(self): from acme.challenges import KeyAuthorizationChallengeResponse response = KeyAuthorizationChallengeResponse( key_authorization='.foo.oKGqedy-b-acd5eoybm2f-' 'NVFxvyOoET5CNy3xnv8WY') - self.assertFalse(response.verify(self.chall, KEY.public_key())) + assert not response.verify(self.chall, KEY.public_key()) class DNS01ResponseTest(unittest.TestCase): @@ -93,11 +92,11 @@ class DNS01ResponseTest(unittest.TestCase): self.response = self.chall.response(KEY) def test_to_partial_json(self): - self.assertEqual({}, self.msg.to_partial_json()) + assert {} == self.msg.to_partial_json() def test_from_json(self): from acme.challenges import DNS01Response - self.assertEqual(self.msg, DNS01Response.from_json(self.jmsg)) + assert self.msg == DNS01Response.from_json(self.jmsg) def test_from_json_hashable(self): from acme.challenges import DNS01Response @@ -107,12 +106,12 @@ class DNS01ResponseTest(unittest.TestCase): key2 = jose.JWKRSA.load(test_util.load_vector('rsa256_key.pem')) public_key = key2.public_key() verified = self.response.simple_verify(self.chall, "local", public_key) - self.assertFalse(verified) + assert not verified def test_simple_verify_success(self): public_key = KEY.public_key() verified = self.response.simple_verify(self.chall, "local", public_key) - self.assertTrue(verified) + assert verified class DNS01Test(unittest.TestCase): @@ -127,20 +126,19 @@ class DNS01Test(unittest.TestCase): } def test_validation_domain_name(self): - self.assertEqual('_acme-challenge.www.example.com', - self.msg.validation_domain_name('www.example.com')) + assert '_acme-challenge.www.example.com' == \ + self.msg.validation_domain_name('www.example.com') def test_validation(self): - self.assertEqual( - "rAa7iIg4K2y63fvUhCfy8dP1Xl7wEhmQq0oChTcE3Zk", - self.msg.validation(KEY)) + assert "rAa7iIg4K2y63fvUhCfy8dP1Xl7wEhmQq0oChTcE3Zk" == \ + self.msg.validation(KEY) def test_to_partial_json(self): - self.assertEqual(self.jmsg, self.msg.to_partial_json()) + assert self.jmsg == self.msg.to_partial_json() def test_from_json(self): from acme.challenges import DNS01 - self.assertEqual(self.msg, DNS01.from_json(self.jmsg)) + assert self.msg == DNS01.from_json(self.jmsg) def test_from_json_hashable(self): from acme.challenges import DNS01 @@ -163,12 +161,11 @@ class HTTP01ResponseTest(unittest.TestCase): self.response = self.chall.response(KEY) def test_to_partial_json(self): - self.assertEqual({}, self.msg.to_partial_json()) + assert {} == self.msg.to_partial_json() def test_from_json(self): from acme.challenges import HTTP01Response - self.assertEqual( - self.msg, HTTP01Response.from_json(self.jmsg)) + assert self.msg == HTTP01Response.from_json(self.jmsg) def test_from_json_hashable(self): from acme.challenges import HTTP01Response @@ -182,16 +179,16 @@ class HTTP01ResponseTest(unittest.TestCase): def test_simple_verify_good_validation(self, mock_get): validation = self.chall.validation(KEY) mock_get.return_value = mock.MagicMock(text=validation) - self.assertTrue(self.response.simple_verify( - self.chall, "local", KEY.public_key())) + assert self.response.simple_verify( + self.chall, "local", KEY.public_key()) mock_get.assert_called_once_with(self.chall.uri("local"), verify=False, timeout=mock.ANY) @mock.patch("acme.challenges.requests.get") def test_simple_verify_bad_validation(self, mock_get): mock_get.return_value = mock.MagicMock(text="!") - self.assertFalse(self.response.simple_verify( - self.chall, "local", KEY.public_key())) + assert not self.response.simple_verify( + self.chall, "local", KEY.public_key()) @mock.patch("acme.challenges.requests.get") def test_simple_verify_whitespace_validation(self, mock_get): @@ -199,24 +196,24 @@ class HTTP01ResponseTest(unittest.TestCase): mock_get.return_value = mock.MagicMock( text=(self.chall.validation(KEY) + HTTP01Response.WHITESPACE_CUTSET)) - self.assertTrue(self.response.simple_verify( - self.chall, "local", KEY.public_key())) + assert self.response.simple_verify( + self.chall, "local", KEY.public_key()) mock_get.assert_called_once_with(self.chall.uri("local"), verify=False, timeout=mock.ANY) @mock.patch("acme.challenges.requests.get") def test_simple_verify_connection_error(self, mock_get): mock_get.side_effect = requests.exceptions.RequestException - self.assertFalse(self.response.simple_verify( - self.chall, "local", KEY.public_key())) + assert not self.response.simple_verify( + self.chall, "local", KEY.public_key()) @mock.patch("acme.challenges.requests.get") def test_simple_verify_port(self, mock_get): self.response.simple_verify( self.chall, domain="local", account_public_key=KEY.public_key(), port=8080) - self.assertEqual("local:8080", urllib_parse.urlparse( - mock_get.mock_calls[0][1][0]).netloc) + assert "local:8080" == urllib_parse.urlparse( + mock_get.mock_calls[0][1][0]).netloc @mock.patch("acme.challenges.requests.get") def test_simple_verify_timeout(self, mock_get): @@ -242,30 +239,28 @@ class HTTP01Test(unittest.TestCase): } def test_path(self): - self.assertEqual(self.msg.path, '/.well-known/acme-challenge/' - 'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA') + assert self.msg.path == '/.well-known/acme-challenge/' \ + 'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA' def test_uri(self): - self.assertEqual( - 'http://example.com/.well-known/acme-challenge/' - 'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA', - self.msg.uri('example.com')) + assert 'http://example.com/.well-known/acme-challenge/' \ + 'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA' == \ + self.msg.uri('example.com') def test_to_partial_json(self): - self.assertEqual(self.jmsg, self.msg.to_partial_json()) + assert self.jmsg == self.msg.to_partial_json() def test_from_json(self): from acme.challenges import HTTP01 - self.assertEqual(self.msg, HTTP01.from_json(self.jmsg)) + assert self.msg == HTTP01.from_json(self.jmsg) def test_from_json_hashable(self): from acme.challenges import HTTP01 hash(HTTP01.from_json(self.jmsg)) def test_good_token(self): - self.assertTrue(self.msg.good_token) - self.assertFalse( - self.msg.update(token=b'..').good_token) + assert self.msg.good_token + assert not self.msg.update(token=b'..').good_token class TLSALPN01ResponseTest(unittest.TestCase): @@ -285,11 +280,11 @@ class TLSALPN01ResponseTest(unittest.TestCase): } def test_to_partial_json(self): - self.assertEqual({}, self.response.to_partial_json()) + assert {} == self.response.to_partial_json() def test_from_json(self): from acme.challenges import TLSALPN01Response - self.assertEqual(self.response, TLSALPN01Response.from_json(self.jmsg)) + assert self.response == TLSALPN01Response.from_json(self.jmsg) def test_from_json_hashable(self): from acme.challenges import TLSALPN01Response @@ -298,23 +293,23 @@ class TLSALPN01ResponseTest(unittest.TestCase): def test_gen_verify_cert(self): key1 = test_util.load_pyopenssl_private_key('rsa512_key.pem') cert, key2 = self.response.gen_cert(self.domain, key1) - self.assertEqual(key1, key2) - self.assertTrue(self.response.verify_cert(self.domain, cert)) + assert key1 == key2 + assert self.response.verify_cert(self.domain, cert) def test_gen_verify_cert_gen_key(self): cert, key = self.response.gen_cert(self.domain) - self.assertIsInstance(key, OpenSSL.crypto.PKey) - self.assertTrue(self.response.verify_cert(self.domain, cert)) + assert isinstance(key, OpenSSL.crypto.PKey) + assert self.response.verify_cert(self.domain, cert) def test_verify_bad_cert(self): - self.assertFalse(self.response.verify_cert(self.domain, - test_util.load_cert('cert.pem'))) + assert not self.response.verify_cert(self.domain, + test_util.load_cert('cert.pem')) def test_verify_bad_domain(self): key1 = test_util.load_pyopenssl_private_key('rsa512_key.pem') cert, key2 = self.response.gen_cert(self.domain, key1) - self.assertEqual(key1, key2) - self.assertFalse(self.response.verify_cert(self.domain2, cert)) + assert key1 == key2 + assert not self.response.verify_cert(self.domain2, cert) def test_simple_verify_bad_key_authorization(self): key2 = jose.JWKRSA.load(test_util.load_vector('rsa256_key.pem')) @@ -323,10 +318,9 @@ class TLSALPN01ResponseTest(unittest.TestCase): @mock.patch('acme.challenges.TLSALPN01Response.verify_cert', autospec=True) def test_simple_verify(self, mock_verify_cert): mock_verify_cert.return_value = mock.sentinel.verification - self.assertEqual( - mock.sentinel.verification, self.response.simple_verify( + assert mock.sentinel.verification == self.response.simple_verify( self.chall, self.domain, KEY.public_key(), - cert=mock.sentinel.cert)) + cert=mock.sentinel.cert) mock_verify_cert.assert_called_once_with( self.response, self.domain, mock.sentinel.cert) @@ -348,8 +342,8 @@ class TLSALPN01ResponseTest(unittest.TestCase): @mock.patch('acme.challenges.TLSALPN01Response.probe_cert') def test_simple_verify_false_on_probe_error(self, mock_probe_cert): mock_probe_cert.side_effect = errors.Error - self.assertFalse(self.response.simple_verify( - self.chall, self.domain, KEY.public_key())) + assert not self.response.simple_verify( + self.chall, self.domain, KEY.public_key()) class TLSALPN01Test(unittest.TestCase): @@ -364,11 +358,11 @@ class TLSALPN01Test(unittest.TestCase): } def test_to_partial_json(self): - self.assertEqual(self.jmsg, self.msg.to_partial_json()) + assert self.jmsg == self.msg.to_partial_json() def test_from_json(self): from acme.challenges import TLSALPN01 - self.assertEqual(self.msg, TLSALPN01.from_json(self.jmsg)) + assert self.msg == TLSALPN01.from_json(self.jmsg) def test_from_json_hashable(self): from acme.challenges import TLSALPN01 @@ -377,14 +371,14 @@ class TLSALPN01Test(unittest.TestCase): def test_from_json_invalid_token_length(self): from acme.challenges import TLSALPN01 self.jmsg['token'] = jose.encode_b64jose(b'abcd') - self.assertRaises( - jose.DeserializationError, TLSALPN01.from_json, self.jmsg) + with pytest.raises(jose.DeserializationError): + TLSALPN01.from_json(self.jmsg) @mock.patch('acme.challenges.TLSALPN01Response.gen_cert') def test_validation(self, mock_gen_cert): mock_gen_cert.return_value = ('cert', 'key') - self.assertEqual(('cert', 'key'), self.msg.validation( - KEY, cert_key=mock.sentinel.cert_key, domain=mock.sentinel.domain)) + assert ('cert', 'key') == self.msg.validation( + KEY, cert_key=mock.sentinel.cert_key, domain=mock.sentinel.domain) mock_gen_cert.assert_called_once_with(key=mock.sentinel.cert_key, domain=mock.sentinel.domain) @@ -401,11 +395,11 @@ class DNSTest(unittest.TestCase): } def test_to_partial_json(self): - self.assertEqual(self.jmsg, self.msg.to_partial_json()) + assert self.jmsg == self.msg.to_partial_json() def test_from_json(self): from acme.challenges import DNS - self.assertEqual(self.msg, DNS.from_json(self.jmsg)) + assert self.msg == DNS.from_json(self.jmsg) def test_from_json_hashable(self): from acme.challenges import DNS @@ -415,13 +409,13 @@ class DNSTest(unittest.TestCase): ec_key_secp384r1 = JWKEC(key=test_util.load_ecdsa_private_key('ec_secp384r1_key.pem')) for key, alg in [(KEY, jose.RS256), (ec_key_secp384r1, jose.ES384)]: with self.subTest(key=key, alg=alg): - self.assertTrue(self.msg.check_validation( - self.msg.gen_validation(key, alg=alg), key.public_key())) + assert self.msg.check_validation( + self.msg.gen_validation(key, alg=alg), key.public_key()) def test_gen_check_validation_wrong_key(self): key2 = jose.JWKRSA.load(test_util.load_vector('rsa1024_key.pem')) - self.assertFalse(self.msg.check_validation( - self.msg.gen_validation(KEY), key2.public_key())) + assert not self.msg.check_validation( + self.msg.gen_validation(KEY), key2.public_key()) def test_check_validation_wrong_payload(self): validations = tuple( @@ -429,33 +423,32 @@ class DNSTest(unittest.TestCase): for payload in (b'', b'{}') ) for validation in validations: - self.assertFalse(self.msg.check_validation( - validation, KEY.public_key())) + assert not self.msg.check_validation( + validation, KEY.public_key()) def test_check_validation_wrong_fields(self): bad_validation = jose.JWS.sign( payload=self.msg.update( token=b'x' * 20).json_dumps().encode('utf-8'), alg=jose.RS256, key=KEY) - self.assertFalse(self.msg.check_validation(bad_validation, KEY.public_key())) + assert not self.msg.check_validation(bad_validation, KEY.public_key()) def test_gen_response(self): with mock.patch('acme.challenges.DNS.gen_validation') as mock_gen: mock_gen.return_value = mock.sentinel.validation response = self.msg.gen_response(KEY) from acme.challenges import DNSResponse - self.assertIsInstance(response, DNSResponse) - self.assertEqual(response.validation, mock.sentinel.validation) + assert isinstance(response, DNSResponse) + assert response.validation == mock.sentinel.validation def test_validation_domain_name(self): - self.assertEqual('_acme-challenge.le.wtf', self.msg.validation_domain_name('le.wtf')) + assert '_acme-challenge.le.wtf' == self.msg.validation_domain_name('le.wtf') def test_validation_domain_name_ecdsa(self): ec_key_secp384r1 = JWKEC(key=test_util.load_ecdsa_private_key('ec_secp384r1_key.pem')) - self.assertIs(self.msg.check_validation( + assert self.msg.check_validation( self.msg.gen_validation(ec_key_secp384r1, alg=jose.ES384), - ec_key_secp384r1.public_key()), True - ) + ec_key_secp384r1.public_key()) is True class DNSResponseTest(unittest.TestCase): @@ -480,18 +473,18 @@ class DNSResponseTest(unittest.TestCase): } def test_to_partial_json(self): - self.assertEqual(self.jmsg_to, self.msg.to_partial_json()) + assert self.jmsg_to == self.msg.to_partial_json() def test_from_json(self): from acme.challenges import DNSResponse - self.assertEqual(self.msg, DNSResponse.from_json(self.jmsg_from)) + assert self.msg == DNSResponse.from_json(self.jmsg_from) def test_from_json_hashable(self): from acme.challenges import DNSResponse hash(DNSResponse.from_json(self.jmsg_from)) def test_check_validation(self): - self.assertTrue(self.msg.check_validation(self.chall, KEY.public_key())) + assert self.msg.check_validation(self.chall, KEY.public_key()) class JWSPayloadRFC8555Compliant(unittest.TestCase): @@ -503,7 +496,7 @@ class JWSPayloadRFC8555Compliant(unittest.TestCase): jobj = challenge_body.json_dumps(indent=2).encode() # RFC8555 states that challenge responses must have an empty payload. - self.assertEqual(jobj, b'{}') + assert jobj == b'{}' if __name__ == '__main__': diff --git a/acme/tests/client_test.py b/acme/tests/client_test.py index ee969683e..79153a31b 100644 --- a/acme/tests/client_test.py +++ b/acme/tests/client_test.py @@ -103,7 +103,7 @@ class ClientV2Test(unittest.TestCase): self.response.json.return_value = self.regr.body.to_json() self.response.headers['Location'] = self.regr.uri - self.assertEqual(self.regr, self.client.new_account(self.new_reg)) + assert self.regr == self.client.new_account(self.new_reg) def test_new_account_tos_link(self): self.response.status_code = http_client.CREATED @@ -113,14 +113,15 @@ class ClientV2Test(unittest.TestCase): 'terms-of-service': {'url': 'https://www.letsencrypt-demo.org/tos'}, }) - self.assertEqual(self.client.new_account(self.new_reg).terms_of_service, - 'https://www.letsencrypt-demo.org/tos') + assert self.client.new_account(self.new_reg).terms_of_service == \ + 'https://www.letsencrypt-demo.org/tos' def test_new_account_conflict(self): self.response.status_code = http_client.OK self.response.headers['Location'] = self.regr.uri - self.assertRaises(errors.ConflictError, self.client.new_account, self.new_reg) + with pytest.raises(errors.ConflictError): + self.client.new_account(self.new_reg) def test_deactivate_account(self): deactivated_regr = self.regr.update( @@ -128,16 +129,16 @@ class ClientV2Test(unittest.TestCase): self.response.json.return_value = deactivated_regr.body.to_json() self.response.status_code = http_client.OK self.response.headers['Location'] = self.regr.uri - self.assertEqual(self.client.deactivate_registration(self.regr), deactivated_regr) + assert self.client.deactivate_registration(self.regr) == deactivated_regr def test_deactivate_authorization(self): deactivated_authz = self.authzr.update( body=self.authzr.body.update(status=messages.STATUS_DEACTIVATED)) self.response.json.return_value = deactivated_authz.body.to_json() authzr = self.client.deactivate_authorization(self.authzr) - self.assertEqual(deactivated_authz.body, authzr.body) - self.assertEqual(self.client.net.post.call_count, 1) - self.assertIn(self.authzr.uri, self.net.post.call_args_list[0][0]) + assert deactivated_authz.body == authzr.body + assert self.client.net.post.call_count == 1 + assert self.authzr.uri in self.net.post.call_args_list[0][0] def test_new_order(self): order_response = copy.deepcopy(self.response) @@ -155,7 +156,7 @@ class ClientV2Test(unittest.TestCase): with mock.patch('acme.client.ClientV2._post_as_get') as mock_post_as_get: mock_post_as_get.side_effect = (authz_response, authz_response2) - self.assertEqual(self.client.new_order(CSR_MIXED_PEM), self.orderr) + assert self.client.new_order(CSR_MIXED_PEM) == self.orderr def test_answer_challege(self): self.response.links['up'] = {'url': self.challr.authzr_uri} @@ -163,13 +164,12 @@ class ClientV2Test(unittest.TestCase): chall_response = challenges.DNSResponse(validation=None) self.client.answer_challenge(self.challr.body, chall_response) - self.assertRaises(errors.UnexpectedUpdate, self.client.answer_challenge, - self.challr.body.update(uri='foo'), chall_response) + with pytest.raises(errors.UnexpectedUpdate): + self.client.answer_challenge(self.challr.body.update(uri='foo'), chall_response) def test_answer_challenge_missing_next(self): - self.assertRaises( - errors.ClientError, self.client.answer_challenge, - self.challr.body, challenges.DNSResponse(validation=None)) + with pytest.raises(errors.ClientError): + self.client.answer_challenge(self.challr.body, challenges.DNSResponse(validation=None)) @mock.patch('acme.client.datetime') def test_poll_and_finalize(self, mock_datetime): @@ -180,7 +180,7 @@ class ClientV2Test(unittest.TestCase): self.client.poll_authorizations = mock.Mock(return_value=self.orderr) self.client.finalize_order = mock.Mock(return_value=self.orderr) - self.assertEqual(self.client.poll_and_finalize(self.orderr), self.orderr) + assert self.client.poll_and_finalize(self.orderr) == self.orderr self.client.poll_authorizations.assert_called_once_with(self.orderr, expected_deadline) self.client.finalize_order.assert_called_once_with(self.orderr, expected_deadline) @@ -193,8 +193,8 @@ class ClientV2Test(unittest.TestCase): self.response.json.side_effect = [ self.authz.to_json(), self.authz2.to_json(), self.authz2.to_json()] - self.assertRaises( - errors.TimeoutError, self.client.poll_authorizations, self.orderr, now_side_effect[1]) + with pytest.raises(errors.TimeoutError): + self.client.poll_authorizations(self.orderr, now_side_effect[1]) def test_poll_authorizations_failure(self): deadline = datetime.datetime(9999, 9, 9) @@ -203,8 +203,8 @@ class ClientV2Test(unittest.TestCase): authz = self.authz.update(status=messages.STATUS_INVALID, challenges=(challb,)) self.response.json.return_value = authz.to_json() - self.assertRaises( - errors.ValidationError, self.client.poll_authorizations, self.orderr, deadline) + with pytest.raises(errors.ValidationError): + self.client.poll_authorizations(self.orderr, deadline) def test_poll_authorizations_success(self): deadline = datetime.datetime(9999, 9, 9) @@ -215,12 +215,13 @@ class ClientV2Test(unittest.TestCase): self.response.json.side_effect = ( self.authz.to_json(), self.authz2.to_json(), updated_authz2.to_json()) - self.assertEqual(self.client.poll_authorizations(self.orderr, deadline), updated_orderr) + assert self.client.poll_authorizations(self.orderr, deadline) == updated_orderr def test_poll_unexpected_update(self): updated_authz = self.authz.update(identifier=self.identifier.update(value='foo')) self.response.json.return_value = updated_authz.to_json() - self.assertRaises(errors.UnexpectedUpdate, self.client.poll, self.authzr) + with pytest.raises(errors.UnexpectedUpdate): + self.client.poll(self.authzr) def test_finalize_order_success(self): updated_order = self.order.update( @@ -232,7 +233,7 @@ class ClientV2Test(unittest.TestCase): self.response.text = CERT_SAN_PEM deadline = datetime.datetime(9999, 9, 9) - self.assertEqual(self.client.finalize_order(self.orderr, deadline), updated_orderr) + assert self.client.finalize_order(self.orderr, deadline) == updated_orderr def test_finalize_order_error(self): updated_order = self.order.update( @@ -241,19 +242,20 @@ class ClientV2Test(unittest.TestCase): self.response.json.return_value = updated_order.to_json() deadline = datetime.datetime(9999, 9, 9) - self.assertRaises(errors.IssuanceError, self.client.finalize_order, self.orderr, deadline) + with pytest.raises(errors.IssuanceError): + self.client.finalize_order(self.orderr, deadline) def test_finalize_order_invalid_status(self): # https://github.com/certbot/certbot/issues/9296 order = self.order.update(error=None, status=messages.STATUS_INVALID) self.response.json.return_value = order.to_json() - with self.assertRaises(errors.Error) as error: + with pytest.raises(errors.Error, match="The certificate order failed"): self.client.finalize_order(self.orderr, datetime.datetime(9999, 9, 9)) - self.assertIn("The certificate order failed", str(error.exception)) def test_finalize_order_timeout(self): deadline = datetime.datetime.now() - datetime.timedelta(seconds=60) - self.assertRaises(errors.TimeoutError, self.client.finalize_order, self.orderr, deadline) + with pytest.raises(errors.TimeoutError): + self.client.finalize_order(self.orderr, deadline) def test_finalize_order_alt_chains(self): updated_order = self.order.update( @@ -276,11 +278,11 @@ class ClientV2Test(unittest.TestCase): mock.ANY, new_nonce_url=mock.ANY) self.net.post.assert_any_call('https://example.com/acme/cert/2', mock.ANY, new_nonce_url=mock.ANY) - self.assertEqual(resp, updated_orderr) + assert resp == updated_orderr del self.response.headers['Link'] resp = self.client.finalize_order(self.orderr, deadline, fetch_alternative_chains=True) - self.assertEqual(resp, updated_orderr.update(alternative_fullchains_pem=[])) + assert resp == updated_orderr.update(alternative_fullchains_pem=[]) def test_revoke(self): self.client.revoke(messages_test.CERT, self.rsn) @@ -289,20 +291,18 @@ class ClientV2Test(unittest.TestCase): def test_revoke_bad_status_raises_error(self): self.response.status_code = http_client.METHOD_NOT_ALLOWED - self.assertRaises( - errors.ClientError, - self.client.revoke, - messages_test.CERT, + with pytest.raises(errors.ClientError): + self.client.revoke(messages_test.CERT, self.rsn) def test_update_registration(self): # "Instance of 'Field' has no to_json/update member" bug: self.response.headers['Location'] = self.regr.uri self.response.json.return_value = self.regr.body.to_json() - self.assertEqual(self.regr, self.client.update_registration(self.regr)) - self.assertIsNotNone(self.client.net.account) - self.assertEqual(self.client.net.post.call_count, 2) - self.assertIn(DIRECTORY_V2.newAccount, self.net.post.call_args_list[0][0]) + assert self.regr == self.client.update_registration(self.regr) + assert self.client.net.account is not None + assert self.client.net.post.call_count == 2 + assert DIRECTORY_V2.newAccount in self.net.post.call_args_list[0][0] self.response.json.return_value = self.regr.body.update( contact=()).to_json() @@ -312,22 +312,22 @@ class ClientV2Test(unittest.TestCase): 'meta': messages.Directory.Meta(external_account_required=True) }) - self.assertTrue(self.client.external_account_required()) + assert self.client.external_account_required() def test_external_account_required_false(self): self.client.directory = messages.Directory({ 'meta': messages.Directory.Meta(external_account_required=False) }) - self.assertFalse(self.client.external_account_required()) + assert not self.client.external_account_required() def test_external_account_required_default(self): - self.assertFalse(self.client.external_account_required()) + assert not self.client.external_account_required() def test_query_registration_client(self): self.response.json.return_value = self.regr.body.to_json() self.response.headers['Location'] = 'https://www.letsencrypt-demo.org/acme/reg/1' - self.assertEqual(self.regr, self.client.query_registration(self.regr)) + assert self.regr == self.client.query_registration(self.regr) def test_post_as_get(self): with mock.patch('acme.client.ClientV2._authzr_from_response') as mock_client: @@ -342,9 +342,8 @@ class ClientV2Test(unittest.TestCase): def test_retry_after_date(self): self.response.headers['Retry-After'] = 'Fri, 31 Dec 1999 23:59:59 GMT' - self.assertEqual( - datetime.datetime(1999, 12, 31, 23, 59, 59), - self.client.retry_after(response=self.response, default=10)) + assert datetime.datetime(1999, 12, 31, 23, 59, 59) == \ + self.client.retry_after(response=self.response, default=10) @mock.patch('acme.client.datetime') def test_retry_after_invalid(self, dt_mock): @@ -352,9 +351,8 @@ class ClientV2Test(unittest.TestCase): dt_mock.timedelta = datetime.timedelta self.response.headers['Retry-After'] = 'foooo' - self.assertEqual( - datetime.datetime(2015, 3, 27, 0, 0, 10), - self.client.retry_after(response=self.response, default=10)) + assert datetime.datetime(2015, 3, 27, 0, 0, 10) == \ + self.client.retry_after(response=self.response, default=10) @mock.patch('acme.client.datetime') def test_retry_after_overflow(self, dt_mock): @@ -363,9 +361,8 @@ class ClientV2Test(unittest.TestCase): dt_mock.datetime.side_effect = datetime.datetime self.response.headers['Retry-After'] = "Tue, 116 Feb 2016 11:50:00 MST" - self.assertEqual( - datetime.datetime(2015, 3, 27, 0, 0, 10), - self.client.retry_after(response=self.response, default=10)) + assert datetime.datetime(2015, 3, 27, 0, 0, 10) == \ + self.client.retry_after(response=self.response, default=10) @mock.patch('acme.client.datetime') def test_retry_after_seconds(self, dt_mock): @@ -373,24 +370,21 @@ class ClientV2Test(unittest.TestCase): dt_mock.timedelta = datetime.timedelta self.response.headers['Retry-After'] = '50' - self.assertEqual( - datetime.datetime(2015, 3, 27, 0, 0, 50), - self.client.retry_after(response=self.response, default=10)) + assert datetime.datetime(2015, 3, 27, 0, 0, 50) == \ + self.client.retry_after(response=self.response, default=10) @mock.patch('acme.client.datetime') def test_retry_after_missing(self, dt_mock): dt_mock.datetime.now.return_value = datetime.datetime(2015, 3, 27) dt_mock.timedelta = datetime.timedelta - self.assertEqual( - datetime.datetime(2015, 3, 27, 0, 0, 10), - self.client.retry_after(response=self.response, default=10)) + assert datetime.datetime(2015, 3, 27, 0, 0, 10) == \ + self.client.retry_after(response=self.response, default=10) def test_get_directory(self): self.response.json.return_value = DIRECTORY_V2.to_json() - self.assertEqual( - DIRECTORY_V2.to_partial_json(), - ClientV2.get_directory('https://example.com/dir', self.net).to_partial_json()) + assert DIRECTORY_V2.to_partial_json() == \ + ClientV2.get_directory('https://example.com/dir', self.net).to_partial_json() class MockJSONDeSerializable(jose.JSONDeSerializable): @@ -422,15 +416,15 @@ class ClientNetworkTest(unittest.TestCase): self.response.links = {} def test_init(self): - self.assertIs(self.net.verify_ssl, self.verify_ssl) + assert self.net.verify_ssl is self.verify_ssl def test_wrap_in_jws(self): # pylint: disable=protected-access jws_dump = self.net._wrap_in_jws( MockJSONDeSerializable('foo'), nonce=b'Tg', url="url") jws = acme_jws.JWS.json_loads(jws_dump) - self.assertEqual(json.loads(jws.payload.decode()), {'foo': 'foo'}) - self.assertEqual(jws.signature.combined.nonce, b'Tg') + assert json.loads(jws.payload.decode()) == {'foo': 'foo'} + assert jws.signature.combined.nonce == b'Tg' def test_wrap_in_jws_v2(self): self.net.account = {'uri': 'acct-uri'} @@ -438,10 +432,10 @@ class ClientNetworkTest(unittest.TestCase): jws_dump = self.net._wrap_in_jws( MockJSONDeSerializable('foo'), nonce=b'Tg', url="url") jws = acme_jws.JWS.json_loads(jws_dump) - self.assertEqual(json.loads(jws.payload.decode()), {'foo': 'foo'}) - self.assertEqual(jws.signature.combined.nonce, b'Tg') - self.assertEqual(jws.signature.combined.kid, u'acct-uri') - self.assertEqual(jws.signature.combined.url, u'url') + assert json.loads(jws.payload.decode()) == {'foo': 'foo'} + assert jws.signature.combined.nonce == b'Tg' + assert jws.signature.combined.kid == u'acct-uri' + assert jws.signature.combined.url == u'url' def test_check_response_not_ok_jobj_no_error(self): self.response.ok = False @@ -449,31 +443,31 @@ class ClientNetworkTest(unittest.TestCase): with mock.patch('acme.client.messages.Error.from_json') as from_json: from_json.side_effect = jose.DeserializationError # pylint: disable=protected-access - self.assertRaises( - errors.ClientError, self.net._check_response, self.response) + with pytest.raises(errors.ClientError): + self.net._check_response(self.response) def test_check_response_not_ok_jobj_error(self): self.response.ok = False self.response.json.return_value = messages.Error.with_code( 'serverInternal', detail='foo', title='some title').to_json() # pylint: disable=protected-access - self.assertRaises( - messages.Error, self.net._check_response, self.response) + with pytest.raises(messages.Error): + self.net._check_response(self.response) def test_check_response_not_ok_no_jobj(self): self.response.ok = False self.response.json.side_effect = ValueError # pylint: disable=protected-access - self.assertRaises( - errors.ClientError, self.net._check_response, self.response) + with pytest.raises(errors.ClientError): + self.net._check_response(self.response) def test_check_response_ok_no_jobj_ct_required(self): self.response.json.side_effect = ValueError for response_ct in [self.net.JSON_CONTENT_TYPE, 'foo']: self.response.headers['Content-Type'] = response_ct # pylint: disable=protected-access - self.assertRaises( - errors.ClientError, self.net._check_response, self.response, + with pytest.raises(errors.ClientError): + self.net._check_response(self.response, content_type=self.net.JSON_CONTENT_TYPE) def test_check_response_ok_no_jobj_no_ct(self): @@ -481,16 +475,15 @@ class ClientNetworkTest(unittest.TestCase): for response_ct in [self.net.JSON_CONTENT_TYPE, 'foo']: self.response.headers['Content-Type'] = response_ct # pylint: disable=protected-access - self.assertEqual( - self.response, self.net._check_response(self.response)) + assert self.response == self.net._check_response(self.response) @mock.patch('acme.client.logger') def test_check_response_ok_ct_with_charset(self, mock_logger): self.response.json.return_value = {} self.response.headers['Content-Type'] = 'application/json; charset=utf-8' # pylint: disable=protected-access - self.assertEqual(self.response, self.net._check_response( - self.response, content_type='application/json')) + assert self.response == self.net._check_response( + self.response, content_type='application/json') try: mock_logger.debug.assert_called_with( 'Ignoring wrong Content-Type (%r) for JSON decodable response', @@ -506,8 +499,8 @@ class ClientNetworkTest(unittest.TestCase): self.response.json.return_value = {} self.response.headers['Content-Type'] = 'text/plain' # pylint: disable=protected-access - self.assertEqual(self.response, self.net._check_response( - self.response, content_type='application/json')) + assert self.response == self.net._check_response( + self.response, content_type='application/json') mock_logger.debug.assert_called_with( 'Ignoring wrong Content-Type (%r) for JSON decodable response', 'text/plain' @@ -517,22 +510,22 @@ class ClientNetworkTest(unittest.TestCase): self.response.ok = False self.response.status_code = 409 # pylint: disable=protected-access - self.assertRaises(errors.ConflictError, self.net._check_response, self.response) + with pytest.raises(errors.ConflictError): + self.net._check_response(self.response) def test_check_response_jobj(self): self.response.json.return_value = {} for response_ct in [self.net.JSON_CONTENT_TYPE, 'foo']: self.response.headers['Content-Type'] = response_ct # pylint: disable=protected-access - self.assertEqual( - self.response, self.net._check_response(self.response)) + assert self.response == self.net._check_response(self.response) def test_send_request(self): self.net.session = mock.MagicMock() self.net.session.request.return_value = self.response # pylint: disable=protected-access - self.assertEqual(self.response, self.net._send_request( - 'HEAD', 'http://example.com/', 'foo', bar='baz')) + assert self.response == self.net._send_request( + 'HEAD', 'http://example.com/', 'foo', bar='baz') self.net.session.request.assert_called_once_with( 'HEAD', 'http://example.com/', 'foo', headers=mock.ANY, verify=mock.ANY, timeout=mock.ANY, bar='baz') @@ -554,8 +547,8 @@ class ClientNetworkTest(unittest.TestCase): self.net.session = mock.MagicMock() self.net.session.request.return_value = self.response # pylint: disable=protected-access - self.assertEqual(self.response, self.net._send_request( - 'POST', 'http://example.com/', 'foo', data='qux', bar='baz')) + assert self.response == self.net._send_request( + 'POST', 'http://example.com/', 'foo', data='qux', bar='baz') self.net.session.request.assert_called_once_with( 'POST', 'http://example.com/', 'foo', headers=mock.ANY, verify=mock.ANY, timeout=mock.ANY, data='qux', bar='baz') @@ -567,9 +560,8 @@ class ClientNetworkTest(unittest.TestCase): self.net.session.request.return_value = self.response self.net.verify_ssl = verify # pylint: disable=protected-access - self.assertEqual( - self.response, - self.net._send_request('GET', 'http://example.com/')) + assert self.response == \ + self.net._send_request('GET', 'http://example.com/') self.net.session.request.assert_called_once_with( 'GET', 'http://example.com/', verify=verify, timeout=mock.ANY, headers=mock.ANY) @@ -617,8 +609,8 @@ class ClientNetworkTest(unittest.TestCase): mock_requests.exceptions = requests.exceptions mock_requests.request.side_effect = requests.exceptions.RequestException # pylint: disable=protected-access - self.assertRaises(requests.exceptions.RequestException, - self.net._send_request, 'GET', 'uri') + with pytest.raises(requests.exceptions.RequestException): + self.net._send_request('GET', 'uri') def test_urllib_error(self): # Using a connection error to test a properly formatted error message @@ -628,12 +620,12 @@ class ClientNetworkTest(unittest.TestCase): # Value Error Generated Exceptions except ValueError as y: - self.assertEqual("Requesting localhost/nonexistent: " - "Connection refused", str(y)) + assert "Requesting localhost/nonexistent: " \ + "Connection refused" == str(y) # Requests Library Exceptions except requests.exceptions.ConnectionError as z: #pragma: no cover - self.assertTrue("'Connection aborted.'" in str(z) or "[WinError 10061]" in str(z)) + assert "'Connection aborted.'" in str(z) or "[WinError 10061]" in str(z) class ClientNetworkWithMockedResponseTest(unittest.TestCase): @@ -660,7 +652,7 @@ class ClientNetworkWithMockedResponseTest(unittest.TestCase): def send_request(*args, **kwargs): # pylint: disable=unused-argument,missing-docstring - self.assertNotIn("new_nonce_url", kwargs) + assert "new_nonce_url" not in kwargs method = args[0] uri = args[1] if method == 'HEAD' and uri != "new_nonce_uri": @@ -684,58 +676,60 @@ class ClientNetworkWithMockedResponseTest(unittest.TestCase): def check_response(self, response, content_type): # pylint: disable=missing-docstring - self.assertEqual(self.response, response) - self.assertEqual(self.content_type, content_type) - self.assertTrue(self.response.ok) + assert self.response == response + assert self.content_type == content_type + assert self.response.ok self.response.checked = True return self.response def test_head(self): - self.assertEqual(self.acmev1_nonce_response, self.net.head( - 'http://example.com/', 'foo', bar='baz')) + assert self.acmev1_nonce_response == self.net.head( + 'http://example.com/', 'foo', bar='baz') self.send_request.assert_called_once_with( 'HEAD', 'http://example.com/', 'foo', bar='baz') def test_head_v2(self): - self.assertEqual(self.response, self.net.head( - 'new_nonce_uri', 'foo', bar='baz')) + assert self.response == self.net.head( + 'new_nonce_uri', 'foo', bar='baz') self.send_request.assert_called_once_with( 'HEAD', 'new_nonce_uri', 'foo', bar='baz') def test_get(self): - self.assertEqual(self.response, self.net.get( - 'http://example.com/', content_type=self.content_type, bar='baz')) - self.assertTrue(self.response.checked) + assert self.response == self.net.get( + 'http://example.com/', content_type=self.content_type, bar='baz') + assert self.response.checked self.send_request.assert_called_once_with( 'GET', 'http://example.com/', bar='baz') def test_post_no_content_type(self): self.content_type = self.net.JOSE_CONTENT_TYPE - self.assertEqual(self.response, self.net.post('uri', self.obj)) - self.assertTrue(self.response.checked) + assert self.response == self.net.post('uri', self.obj) + assert self.response.checked def test_post(self): # pylint: disable=protected-access - self.assertEqual(self.response, self.net.post( - 'uri', self.obj, content_type=self.content_type)) - self.assertTrue(self.response.checked) + assert self.response == self.net.post( + 'uri', self.obj, content_type=self.content_type) + assert self.response.checked self.net._wrap_in_jws.assert_called_once_with( self.obj, jose.b64decode(self.all_nonces.pop()), "uri") self.available_nonces = [] - self.assertRaises(errors.MissingNonce, self.net.post, - 'uri', self.obj, content_type=self.content_type) + with pytest.raises(errors.MissingNonce): + self.net.post('uri', self.obj, content_type=self.content_type) self.net._wrap_in_jws.assert_called_with( self.obj, jose.b64decode(self.all_nonces.pop()), "uri") def test_post_wrong_initial_nonce(self): # HEAD self.available_nonces = [b'f', jose.b64encode(b'good')] - self.assertRaises(errors.BadNonce, self.net.post, 'uri', + with pytest.raises(errors.BadNonce): + self.net.post('uri', self.obj, content_type=self.content_type) def test_post_wrong_post_response_nonce(self): self.available_nonces = [jose.b64encode(b'good'), b'f'] - self.assertRaises(errors.BadNonce, self.net.post, 'uri', + with pytest.raises(errors.BadNonce): + self.net.post('uri', self.obj, content_type=self.content_type) def test_post_failed_retry(self): @@ -744,7 +738,8 @@ class ClientNetworkWithMockedResponseTest(unittest.TestCase): # pylint: disable=protected-access self.net._check_response = check_response - self.assertRaises(messages.Error, self.net.post, 'uri', + with pytest.raises(messages.Error): + self.net.post('uri', self.obj, content_type=self.content_type) def test_post_not_retried(self): @@ -754,7 +749,8 @@ class ClientNetworkWithMockedResponseTest(unittest.TestCase): # pylint: disable=protected-access self.net._check_response = check_response - self.assertRaises(messages.Error, self.net.post, 'uri', + with pytest.raises(messages.Error): + self.net.post('uri', self.obj, content_type=self.content_type) def test_post_successful_retry(self): @@ -763,16 +759,16 @@ class ClientNetworkWithMockedResponseTest(unittest.TestCase): self.response] # pylint: disable=protected-access - self.assertEqual(self.response, self.net.post( - 'uri', self.obj, content_type=self.content_type)) + assert self.response == self.net.post( + 'uri', self.obj, content_type=self.content_type) def test_head_get_post_error_passthrough(self): self.send_request.side_effect = requests.exceptions.RequestException for method in self.net.head, self.net.get: - self.assertRaises( - requests.exceptions.RequestException, method, 'GET', 'uri') - self.assertRaises(requests.exceptions.RequestException, - self.net.post, 'uri', obj=self.obj) + with pytest.raises(requests.exceptions.RequestException): + method('GET', 'uri') + with pytest.raises(requests.exceptions.RequestException): + self.net.post('uri', obj=self.obj) def test_post_bad_nonce_head(self): # pylint: disable=protected-access @@ -783,10 +779,11 @@ class ClientNetworkWithMockedResponseTest(unittest.TestCase): self.content_type = None check_response = mock.MagicMock() self.net._check_response = check_response - self.assertRaises(errors.ClientError, self.net.post, 'uri', + with pytest.raises(errors.ClientError): + self.net.post('uri', self.obj, content_type=self.content_type, new_nonce_url='new_nonce_uri') - self.assertEqual(check_response.call_count, 1) + assert check_response.call_count == 1 def test_new_nonce_uri_removed(self): self.content_type = None diff --git a/acme/tests/crypto_util_test.py b/acme/tests/crypto_util_test.py index 008430ac4..409a2ce27 100644 --- a/acme/tests/crypto_util_test.py +++ b/acme/tests/crypto_util_test.py @@ -56,18 +56,20 @@ class SSLSocketAndProbeSNITest(unittest.TestCase): def test_probe_ok(self): self._start_server() - self.assertEqual(self.cert, self._probe(b'foo')) + assert self.cert == self._probe(b'foo') def test_probe_not_recognized_name(self): self._start_server() - self.assertRaises(errors.Error, self._probe, b'bar') + with pytest.raises(errors.Error): + self._probe(b'bar') def test_probe_connection_error(self): self.server.server_close() original_timeout = socket.getdefaulttimeout() try: socket.setdefaulttimeout(1) - self.assertRaises(errors.Error, self._probe, b'bar') + with pytest.raises(errors.Error): + self._probe(b'bar') finally: socket.setdefaulttimeout(original_timeout) @@ -77,10 +79,10 @@ class SSLSocketTest(unittest.TestCase): def test_ssl_socket_invalid_arguments(self): from acme.crypto_util import SSLSocket - with self.assertRaises(ValueError): + with pytest.raises(ValueError): _ = SSLSocket(None, {'sni': ('key', 'cert')}, cert_selection=lambda _: None) - with self.assertRaises(ValueError): + with pytest.raises(ValueError): _ = SSLSocket(None) @@ -97,15 +99,15 @@ class PyOpenSSLCertOrReqAllNamesTest(unittest.TestCase): return self._call(test_util.load_cert, name) def test_cert_one_san_no_common(self): - self.assertEqual(self._call_cert('cert-nocn.der'), - ['no-common-name.badssl.com']) + assert self._call_cert('cert-nocn.der') == \ + ['no-common-name.badssl.com'] def test_cert_no_sans_yes_common(self): - self.assertEqual(self._call_cert('cert.pem'), ['example.com']) + assert self._call_cert('cert.pem') == ['example.com'] def test_cert_two_sans_yes_common(self): - self.assertEqual(self._call_cert('cert-san.pem'), - ['example.com', 'www.example.com']) + assert self._call_cert('cert-san.pem') == \ + ['example.com', 'www.example.com'] class PyOpenSSLCertOrReqSANTest(unittest.TestCase): @@ -133,47 +135,47 @@ class PyOpenSSLCertOrReqSANTest(unittest.TestCase): return self._call(test_util.load_csr, name) def test_cert_no_sans(self): - self.assertEqual(self._call_cert('cert.pem'), []) + assert self._call_cert('cert.pem') == [] def test_cert_two_sans(self): - self.assertEqual(self._call_cert('cert-san.pem'), - ['example.com', 'www.example.com']) + assert self._call_cert('cert-san.pem') == \ + ['example.com', 'www.example.com'] def test_cert_hundred_sans(self): - self.assertEqual(self._call_cert('cert-100sans.pem'), - ['example{0}.com'.format(i) for i in range(1, 101)]) + assert self._call_cert('cert-100sans.pem') == \ + ['example{0}.com'.format(i) for i in range(1, 101)] def test_cert_idn_sans(self): - self.assertEqual(self._call_cert('cert-idnsans.pem'), - self._get_idn_names()) + assert self._call_cert('cert-idnsans.pem') == \ + self._get_idn_names() def test_csr_no_sans(self): - self.assertEqual(self._call_csr('csr-nosans.pem'), []) + assert self._call_csr('csr-nosans.pem') == [] def test_csr_one_san(self): - self.assertEqual(self._call_csr('csr.pem'), ['example.com']) + assert self._call_csr('csr.pem') == ['example.com'] def test_csr_two_sans(self): - self.assertEqual(self._call_csr('csr-san.pem'), - ['example.com', 'www.example.com']) + assert self._call_csr('csr-san.pem') == \ + ['example.com', 'www.example.com'] def test_csr_six_sans(self): - self.assertEqual(self._call_csr('csr-6sans.pem'), + assert self._call_csr('csr-6sans.pem') == \ ['example.com', 'example.org', 'example.net', 'example.info', 'subdomain.example.com', - 'other.subdomain.example.com']) + 'other.subdomain.example.com'] def test_csr_hundred_sans(self): - self.assertEqual(self._call_csr('csr-100sans.pem'), - ['example{0}.com'.format(i) for i in range(1, 101)]) + assert self._call_csr('csr-100sans.pem') == \ + ['example{0}.com'.format(i) for i in range(1, 101)] def test_csr_idn_sans(self): - self.assertEqual(self._call_csr('csr-idnsans.pem'), - self._get_idn_names()) + assert self._call_csr('csr-idnsans.pem') == \ + self._get_idn_names() def test_critical_san(self): - self.assertEqual(self._call_cert('critical-san.pem'), - ['chicago-cubs.venafi.example', 'cubs.venafi.example']) + assert self._call_cert('critical-san.pem') == \ + ['chicago-cubs.venafi.example', 'cubs.venafi.example'] class PyOpenSSLCertOrReqSANIPTest(unittest.TestCase): @@ -192,30 +194,30 @@ class PyOpenSSLCertOrReqSANIPTest(unittest.TestCase): return self._call(test_util.load_csr, name) def test_cert_no_sans(self): - self.assertEqual(self._call_cert('cert.pem'), []) + assert self._call_cert('cert.pem') == [] def test_csr_no_sans(self): - self.assertEqual(self._call_csr('csr-nosans.pem'), []) + assert self._call_csr('csr-nosans.pem') == [] def test_cert_domain_sans(self): - self.assertEqual(self._call_cert('cert-san.pem'), []) + assert self._call_cert('cert-san.pem') == [] def test_csr_domain_sans(self): - self.assertEqual(self._call_csr('csr-san.pem'), []) + assert self._call_csr('csr-san.pem') == [] def test_cert_ip_two_sans(self): - self.assertEqual(self._call_cert('cert-ipsans.pem'), ['192.0.2.145', '203.0.113.1']) + assert self._call_cert('cert-ipsans.pem') == ['192.0.2.145', '203.0.113.1'] def test_csr_ip_two_sans(self): - self.assertEqual(self._call_csr('csr-ipsans.pem'), ['192.0.2.145', '203.0.113.1']) + assert self._call_csr('csr-ipsans.pem') == ['192.0.2.145', '203.0.113.1'] def test_csr_ipv6_sans(self): - self.assertEqual(self._call_csr('csr-ipv6sans.pem'), - ['0:0:0:0:0:0:0:1', 'A3BE:32F3:206E:C75D:956:CEE:9858:5EC5']) + assert self._call_csr('csr-ipv6sans.pem') == \ + ['0:0:0:0:0:0:0:1', 'A3BE:32F3:206E:C75D:956:CEE:9858:5EC5'] def test_cert_ipv6_sans(self): - self.assertEqual(self._call_cert('cert-ipv6sans.pem'), - ['0:0:0:0:0:0:0:1', 'A3BE:32F3:206E:C75D:956:CEE:9858:5EC5']) + assert self._call_cert('cert-ipv6sans.pem') == \ + ['0:0:0:0:0:0:0:1', 'A3BE:32F3:206E:C75D:956:CEE:9858:5EC5'] class GenSsCertTest(unittest.TestCase): @@ -234,12 +236,12 @@ class GenSsCertTest(unittest.TestCase): cert = gen_ss_cert(self.key, ['dummy'], force_san=True, ips=[ipaddress.ip_address("10.10.10.10")]) self.serial_num.append(cert.get_serial_number()) - self.assertGreaterEqual(len(set(self.serial_num)), self.cert_count) + assert len(set(self.serial_num)) >= self.cert_count def test_no_name(self): from acme.crypto_util import gen_ss_cert - with self.assertRaises(AssertionError): + with pytest.raises(AssertionError): gen_ss_cert(self.key, ips=[ipaddress.ip_address("1.1.1.1")]) gen_ss_cert(self.key) @@ -257,41 +259,39 @@ class MakeCSRTest(unittest.TestCase): def test_make_csr(self): csr_pem = self._call_with_key(["a.example", "b.example"]) - self.assertIn(b'--BEGIN CERTIFICATE REQUEST--', csr_pem) - self.assertIn(b'--END CERTIFICATE REQUEST--', csr_pem) + assert b'--BEGIN CERTIFICATE REQUEST--' in csr_pem + assert b'--END CERTIFICATE REQUEST--' in csr_pem csr = OpenSSL.crypto.load_certificate_request( OpenSSL.crypto.FILETYPE_PEM, csr_pem) # In pyopenssl 0.13 (used with TOXENV=py27-oldest), csr objects don't # have a get_extensions() method, so we skip this test if the method # isn't available. if hasattr(csr, 'get_extensions'): - self.assertEqual(len(csr.get_extensions()), 1) - self.assertEqual(csr.get_extensions()[0].get_data(), + assert len(csr.get_extensions()) == 1 + assert csr.get_extensions()[0].get_data() == \ OpenSSL.crypto.X509Extension( b'subjectAltName', critical=False, value=b'DNS:a.example, DNS:b.example', - ).get_data(), - ) + ).get_data() def test_make_csr_ip(self): csr_pem = self._call_with_key(["a.example"], False, [ipaddress.ip_address('127.0.0.1'), ipaddress.ip_address('::1')]) - self.assertIn(b'--BEGIN CERTIFICATE REQUEST--' , csr_pem) - self.assertIn(b'--END CERTIFICATE REQUEST--' , csr_pem) + assert b'--BEGIN CERTIFICATE REQUEST--' in csr_pem + assert b'--END CERTIFICATE REQUEST--' in csr_pem csr = OpenSSL.crypto.load_certificate_request( OpenSSL.crypto.FILETYPE_PEM, csr_pem) # In pyopenssl 0.13 (used with TOXENV=py27-oldest), csr objects don't # have a get_extensions() method, so we skip this test if the method # isn't available. if hasattr(csr, 'get_extensions'): - self.assertEqual(len(csr.get_extensions()), 1) - self.assertEqual(csr.get_extensions()[0].get_data(), + assert len(csr.get_extensions()) == 1 + assert csr.get_extensions()[0].get_data() == \ OpenSSL.crypto.X509Extension( b'subjectAltName', critical=False, value=b'DNS:a.example, IP:127.0.0.1, IP:::1', - ).get_data(), - ) + ).get_data() # for IP san it's actually need to be octet-string, # but somewhere downstream thankfully handle it for us @@ -304,25 +304,26 @@ class MakeCSRTest(unittest.TestCase): # have a get_extensions() method, so we skip this test if the method # isn't available. if hasattr(csr, 'get_extensions'): - self.assertEqual(len(csr.get_extensions()), 2) + assert len(csr.get_extensions()) == 2 # NOTE: Ideally we would filter by the TLS Feature OID, but # OpenSSL.crypto.X509Extension doesn't give us the extension's raw OID, # and the shortname field is just "UNDEF" must_staple_exts = [e for e in csr.get_extensions() if e.get_data() == b"0\x03\x02\x01\x05"] - self.assertEqual(len(must_staple_exts), 1, - "Expected exactly one Must Staple extension") + assert len(must_staple_exts) == 1, \ + "Expected exactly one Must Staple extension" def test_make_csr_without_hostname(self): - self.assertRaises(ValueError, self._call_with_key) + with pytest.raises(ValueError): + self._call_with_key() def test_make_csr_correct_version(self): csr_pem = self._call_with_key(["a.example"]) csr = OpenSSL.crypto.load_certificate_request( OpenSSL.crypto.FILETYPE_PEM, csr_pem) - self.assertEqual(csr.get_version(), 0, - "Expected CSR version to be v1 (encoded as 0), per RFC 2986, section 4") + assert csr.get_version() == 0, \ + "Expected CSR version to be v1 (encoded as 0), per RFC 2986, section 4" class DumpPyopensslChainTest(unittest.TestCase): @@ -340,7 +341,7 @@ class DumpPyopensslChainTest(unittest.TestCase): length = sum( len(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)) for cert in loaded) - self.assertEqual(len(self._call(loaded)), length) + assert len(self._call(loaded)) == length def test_dump_pyopenssl_chain_wrapped(self): names = ['cert.pem', 'cert-san.pem', 'cert-idnsans.pem'] @@ -349,7 +350,7 @@ class DumpPyopensslChainTest(unittest.TestCase): wrapped = [wrap_func(cert) for cert in loaded] dump_func = OpenSSL.crypto.dump_certificate length = sum(len(dump_func(OpenSSL.crypto.FILETYPE_PEM, cert)) for cert in loaded) - self.assertEqual(len(self._call(wrapped)), length) + assert len(self._call(wrapped)) == length if __name__ == '__main__': diff --git a/acme/tests/errors_test.py b/acme/tests/errors_test.py index 0e9f10fe1..97f739d40 100644 --- a/acme/tests/errors_test.py +++ b/acme/tests/errors_test.py @@ -14,7 +14,7 @@ class BadNonceTest(unittest.TestCase): self.error = BadNonce(nonce="xxx", error="error") def test_str(self): - self.assertEqual("Invalid nonce ('xxx'): error", str(self.error)) + assert "Invalid nonce ('xxx'): error" == str(self.error) class MissingNonceTest(unittest.TestCase): @@ -27,8 +27,8 @@ class MissingNonceTest(unittest.TestCase): self.error = MissingNonce(self.response) def test_str(self): - self.assertIn("FOO", str(self.error)) - self.assertIn("{}", str(self.error)) + assert "FOO" in str(self.error) + assert "{}" in str(self.error) class PollErrorTest(unittest.TestCase): @@ -43,12 +43,12 @@ class PollErrorTest(unittest.TestCase): mock.sentinel.AR: mock.sentinel.AR2}) def test_timeout(self): - self.assertTrue(self.timeout.timeout) - self.assertFalse(self.invalid.timeout) + assert self.timeout.timeout + assert not self.invalid.timeout def test_repr(self): - self.assertEqual('PollError(exhausted=%s, updated={sentinel.AR: ' - 'sentinel.AR2})' % repr(set()), repr(self.invalid)) + assert 'PollError(exhausted=%s, updated={sentinel.AR: ' \ + 'sentinel.AR2})' % repr(set()) == repr(self.invalid) if __name__ == "__main__": diff --git a/acme/tests/fields_test.py b/acme/tests/fields_test.py index f07759397..a45bdc47b 100644 --- a/acme/tests/fields_test.py +++ b/acme/tests/fields_test.py @@ -17,16 +17,17 @@ class FixedTest(unittest.TestCase): self.field = fixed('name', 'x') def test_decode(self): - self.assertEqual('x', self.field.decode('x')) + assert 'x' == self.field.decode('x') def test_decode_bad(self): - self.assertRaises(jose.DeserializationError, self.field.decode, 'y') + with pytest.raises(jose.DeserializationError): + self.field.decode('y') def test_encode(self): - self.assertEqual('x', self.field.encode('x')) + assert 'x' == self.field.encode('x') def test_encode_override(self): - self.assertEqual('y', self.field.encode('y')) + assert 'y' == self.field.encode('y') class RFC3339FieldTest(unittest.TestCase): @@ -38,23 +39,21 @@ class RFC3339FieldTest(unittest.TestCase): def test_default_encoder(self): from acme.fields import RFC3339Field - self.assertEqual( - self.encoded, RFC3339Field.default_encoder(self.decoded)) + assert self.encoded == RFC3339Field.default_encoder(self.decoded) def test_default_encoder_naive_fails(self): from acme.fields import RFC3339Field - self.assertRaises( - ValueError, RFC3339Field.default_encoder, datetime.datetime.now()) + with pytest.raises(ValueError): + RFC3339Field.default_encoder(datetime.datetime.now()) def test_default_decoder(self): from acme.fields import RFC3339Field - self.assertEqual( - self.decoded, RFC3339Field.default_decoder(self.encoded)) + assert self.decoded == RFC3339Field.default_decoder(self.encoded) def test_default_decoder_raises_deserialization_error(self): from acme.fields import RFC3339Field - self.assertRaises( - jose.DeserializationError, RFC3339Field.default_decoder, '') + with pytest.raises(jose.DeserializationError): + RFC3339Field.default_decoder('') if __name__ == '__main__': diff --git a/acme/tests/jose_test.py b/acme/tests/jose_test.py index b0b7194fe..67964022d 100644 --- a/acme/tests/jose_test.py +++ b/acme/tests/jose_test.py @@ -19,8 +19,8 @@ class JoseTest(unittest.TestCase): acme_jose_mod = importlib.import_module(acme_jose_path) josepy_mod = importlib.import_module(josepy_path) - self.assertIs(acme_jose_mod, josepy_mod) - self.assertIs(getattr(acme_jose_mod, attribute), getattr(josepy_mod, attribute)) + assert acme_jose_mod is josepy_mod + assert getattr(acme_jose_mod, attribute) is getattr(josepy_mod, attribute) # We use the imports below with eval, but pylint doesn't # understand that. @@ -29,8 +29,8 @@ class JoseTest(unittest.TestCase): import acme # pylint: disable=unused-import acme_jose_mod = eval(acme_jose_path) # pylint: disable=eval-used josepy_mod = eval(josepy_path) # pylint: disable=eval-used - self.assertIs(acme_jose_mod, josepy_mod) - self.assertIs(getattr(acme_jose_mod, attribute), getattr(josepy_mod, attribute)) + assert acme_jose_mod is josepy_mod + assert getattr(acme_jose_mod, attribute) is getattr(josepy_mod, attribute) def test_top_level(self): self._test_it('', 'RS512') diff --git a/acme/tests/jws_test.py b/acme/tests/jws_test.py index 96e0e7d4d..901ae970b 100644 --- a/acme/tests/jws_test.py +++ b/acme/tests/jws_test.py @@ -27,9 +27,9 @@ class HeaderTest(unittest.TestCase): from acme.jws import Header nonce_field = Header._fields['nonce'] - self.assertRaises( - jose.DeserializationError, nonce_field.decode, self.wrong_nonce) - self.assertEqual(b'foo', nonce_field.decode(self.good_nonce)) + with pytest.raises(jose.DeserializationError): + nonce_field.decode(self.wrong_nonce) + assert b'foo' == nonce_field.decode(self.good_nonce) class JWSTest(unittest.TestCase): @@ -47,21 +47,21 @@ class JWSTest(unittest.TestCase): jws = JWS.sign(payload=b'foo', key=self.privkey, alg=jose.RS256, nonce=self.nonce, url=self.url, kid=self.kid) - self.assertEqual(jws.signature.combined.nonce, self.nonce) - self.assertEqual(jws.signature.combined.url, self.url) - self.assertEqual(jws.signature.combined.kid, self.kid) - self.assertIsNone(jws.signature.combined.jwk) + assert jws.signature.combined.nonce == self.nonce + assert jws.signature.combined.url == self.url + assert jws.signature.combined.kid == self.kid + assert jws.signature.combined.jwk is None # TODO: check that nonce is in protected header - self.assertEqual(jws, JWS.from_json(jws.to_json())) + assert jws == JWS.from_json(jws.to_json()) def test_jwk_serialize(self): from acme.jws import JWS jws = JWS.sign(payload=b'foo', key=self.privkey, alg=jose.RS256, nonce=self.nonce, url=self.url) - self.assertIsNone(jws.signature.combined.kid) - self.assertEqual(jws.signature.combined.jwk, self.pubkey) + assert jws.signature.combined.kid is None + assert jws.signature.combined.jwk == self.pubkey if __name__ == '__main__': diff --git a/acme/tests/messages_test.py b/acme/tests/messages_test.py index 22a22e228..781a1b1ac 100644 --- a/acme/tests/messages_test.py +++ b/acme/tests/messages_test.py @@ -39,11 +39,11 @@ class ErrorTest(unittest.TestCase): def test_default_typ(self): from acme.messages import Error - self.assertEqual(Error().typ, 'about:blank') + assert Error().typ == 'about:blank' def test_from_json_empty(self): from acme.messages import Error - self.assertEqual(Error(), Error.from_json('{}')) + assert Error() == Error.from_json('{}') def test_from_json_hashable(self): from acme.messages import Error @@ -54,63 +54,62 @@ class ErrorTest(unittest.TestCase): parsed_error = Error.from_json(self.error_with_subproblems.to_json()) - self.assertEqual(1, len(parsed_error.subproblems)) - self.assertEqual(self.subproblem, parsed_error.subproblems[0]) + assert 1 == len(parsed_error.subproblems) + assert self.subproblem == parsed_error.subproblems[0] def test_description(self): - self.assertEqual('The request message was malformed', self.error.description) - self.assertIsNone(self.error_custom.description) + assert 'The request message was malformed' == self.error.description + assert self.error_custom.description is None def test_code(self): from acme.messages import Error - self.assertEqual('malformed', self.error.code) - self.assertIsNone(self.error_custom.code) - self.assertIsNone(Error().code) + assert 'malformed' == self.error.code + assert self.error_custom.code is None + assert Error().code is None def test_is_acme_error(self): from acme.messages import Error from acme.messages import is_acme_error - self.assertTrue(is_acme_error(self.error)) - self.assertFalse(is_acme_error(self.error_custom)) - self.assertFalse(is_acme_error(Error())) - self.assertFalse(is_acme_error(self.empty_error)) - self.assertFalse(is_acme_error("must pet all the {dogs|rabbits}")) + assert is_acme_error(self.error) + assert not is_acme_error(self.error_custom) + assert not is_acme_error(Error()) + assert not is_acme_error(self.empty_error) + assert not is_acme_error("must pet all the {dogs|rabbits}") def test_unicode_error(self): from acme.messages import Error from acme.messages import is_acme_error arabic_error = Error.with_code( 'malformed', detail=u'\u0639\u062f\u0627\u0644\u0629', title='title') - self.assertTrue(is_acme_error(arabic_error)) + assert is_acme_error(arabic_error) def test_with_code(self): from acme.messages import Error from acme.messages import is_acme_error - self.assertTrue(is_acme_error(Error.with_code('badCSR'))) - self.assertRaises(ValueError, Error.with_code, 'not an ACME error code') + assert is_acme_error(Error.with_code('badCSR')) + with pytest.raises(ValueError): + Error.with_code('not an ACME error code') def test_str(self): - self.assertEqual( - str(self.error), - u"{0.typ} :: {0.description} :: {0.detail} :: {0.title}" - .format(self.error)) - self.assertEqual( - str(self.error_with_subproblems), + assert str(self.error) == \ + u"{0.typ} :: {0.description} :: {0.detail} :: {0.title}" \ + .format(self.error) + assert str(self.error_with_subproblems) == \ (u"{0.typ} :: {0.description} :: {0.detail} :: {0.title}\n"+ u"Problem for {1.identifier.value}: {1.typ} :: {1.description} :: {1.detail} :: {1.title}").format( - self.error_with_subproblems, self.subproblem)) + self.error_with_subproblems, self.subproblem) # this test is based on a minimal reproduction of a contextmanager/immutable # exception related error: https://github.com/python/cpython/issues/99856 def test_setting_traceback(self): - self.assertIsNone(self.error_custom.__traceback__) + assert self.error_custom.__traceback__ is None try: 1/0 except ZeroDivisionError as e: self.error_custom.__traceback__ = e.__traceback__ - self.assertIsNotNone(self.error_custom.__traceback__) + assert self.error_custom.__traceback__ is not None class ConstantTest(unittest.TestCase): @@ -127,28 +126,28 @@ class ConstantTest(unittest.TestCase): self.const_b = MockConstant('b') def test_to_partial_json(self): - self.assertEqual('a', self.const_a.to_partial_json()) - self.assertEqual('b', self.const_b.to_partial_json()) + assert 'a' == self.const_a.to_partial_json() + assert 'b' == self.const_b.to_partial_json() def test_from_json(self): - self.assertEqual(self.const_a, self.MockConstant.from_json('a')) - self.assertRaises( - jose.DeserializationError, self.MockConstant.from_json, 'c') + assert self.const_a == self.MockConstant.from_json('a') + with pytest.raises(jose.DeserializationError): + self.MockConstant.from_json('c') def test_from_json_hashable(self): hash(self.MockConstant.from_json('a')) def test_repr(self): - self.assertEqual('MockConstant(a)', repr(self.const_a)) - self.assertEqual('MockConstant(b)', repr(self.const_b)) + assert 'MockConstant(a)' == repr(self.const_a) + assert 'MockConstant(b)' == repr(self.const_b) def test_equality(self): const_a_prime = self.MockConstant('a') - self.assertNotEqual(self.const_a, self.const_b) - self.assertEqual(self.const_a, const_a_prime) + assert self.const_a != self.const_b + assert self.const_a == const_a_prime - self.assertNotEqual(self.const_a, self.const_b) - self.assertEqual(self.const_a, const_a_prime) + assert self.const_a != self.const_b + assert self.const_a == const_a_prime class DirectoryTest(unittest.TestCase): @@ -171,19 +170,21 @@ class DirectoryTest(unittest.TestCase): Directory({'foo': 'bar'}) def test_getitem(self): - self.assertEqual('reg', self.dir['newReg']) + assert 'reg' == self.dir['newReg'] def test_getitem_fails_with_key_error(self): - self.assertRaises(KeyError, self.dir.__getitem__, 'foo') + with pytest.raises(KeyError): + self.dir.__getitem__('foo') def test_getattr(self): - self.assertEqual('reg', self.dir.newReg) + assert 'reg' == self.dir.newReg def test_getattr_fails_with_attribute_error(self): - self.assertRaises(AttributeError, self.dir.__getattr__, 'foo') + with pytest.raises(AttributeError): + self.dir.__getattr__('foo') def test_to_json(self): - self.assertEqual(self.dir.to_json(), { + assert self.dir.to_json() == { 'newReg': 'reg', 'newCert': 'cert', 'meta': { @@ -191,7 +192,7 @@ class DirectoryTest(unittest.TestCase): 'website': 'https://www.example.com/', 'caaIdentities': ['example.com'], }, - }) + } def test_from_json_deserialization_unknown_key_success(self): # pylint: disable=no-self-use from acme.messages import Directory @@ -202,7 +203,7 @@ class DirectoryTest(unittest.TestCase): for k in self.dir.meta: if k == 'terms_of_service': result = self.dir.meta[k] == 'https://example.com/acme/terms' - self.assertTrue(result) + assert result class ExternalAccountBindingTest(unittest.TestCase): @@ -219,8 +220,8 @@ class ExternalAccountBindingTest(unittest.TestCase): from acme.messages import ExternalAccountBinding eab = ExternalAccountBinding.from_data(self.key, self.kid, self.hmac_key, self.dir) - self.assertEqual(len(eab), 3) - self.assertEqual(sorted(eab.keys()), sorted(['protected', 'payload', 'signature'])) + assert len(eab) == 3 + assert sorted(eab.keys()) == sorted(['protected', 'payload', 'signature']) class RegistrationTest(unittest.TestCase): @@ -249,10 +250,10 @@ class RegistrationTest(unittest.TestCase): def test_from_data(self): from acme.messages import Registration reg = Registration.from_data(phone='1234', email='admin@foo.com') - self.assertEqual(reg.contact, ( + assert reg.contact == ( 'tel:1234', 'mailto:admin@foo.com', - )) + ) def test_new_registration_from_data_with_eab(self): from acme.messages import Directory @@ -266,24 +267,24 @@ class RegistrationTest(unittest.TestCase): }) eab = ExternalAccountBinding.from_data(key, kid, hmac_key, directory) reg = NewRegistration.from_data(email='admin@foo.com', external_account_binding=eab) - self.assertEqual(reg.contact, ( + assert reg.contact == ( 'mailto:admin@foo.com', - )) - self.assertEqual(sorted(reg.external_account_binding.keys()), - sorted(['protected', 'payload', 'signature'])) + ) + assert sorted(reg.external_account_binding.keys()) == \ + sorted(['protected', 'payload', 'signature']) def test_phones(self): - self.assertEqual(('1234',), self.reg.phones) + assert ('1234',) == self.reg.phones def test_emails(self): - self.assertEqual(('admin@foo.com',), self.reg.emails) + assert ('admin@foo.com',) == self.reg.emails def test_to_partial_json(self): - self.assertEqual(self.jobj_to, self.reg.to_partial_json()) + assert self.jobj_to == self.reg.to_partial_json() def test_from_json(self): from acme.messages import Registration - self.assertEqual(self.reg, Registration.from_json(self.jobj_from)) + assert self.reg == Registration.from_json(self.jobj_from) def test_from_json_hashable(self): from acme.messages import Registration @@ -294,13 +295,13 @@ class RegistrationTest(unittest.TestCase): empty_new_reg = NewRegistration() new_reg_with_contact = NewRegistration(contact=()) - self.assertEqual(empty_new_reg.contact, ()) - self.assertEqual(new_reg_with_contact.contact, ()) + assert empty_new_reg.contact == () + assert new_reg_with_contact.contact == () - self.assertNotIn('contact', empty_new_reg.to_partial_json()) - self.assertNotIn('contact', empty_new_reg.fields_to_partial_json()) - self.assertIn('contact', new_reg_with_contact.to_partial_json()) - self.assertIn('contact', new_reg_with_contact.fields_to_partial_json()) + assert 'contact' not in empty_new_reg.to_partial_json() + assert 'contact' not in empty_new_reg.fields_to_partial_json() + assert 'contact' in new_reg_with_contact.to_partial_json() + assert 'contact' in new_reg_with_contact.fields_to_partial_json() class UpdateRegistrationTest(unittest.TestCase): @@ -309,9 +310,8 @@ class UpdateRegistrationTest(unittest.TestCase): def test_empty(self): from acme.messages import UpdateRegistration jstring = '{"resource": "reg"}' - self.assertEqual('{}', UpdateRegistration().json_dumps()) - self.assertEqual( - UpdateRegistration(), UpdateRegistration.json_loads(jstring)) + assert '{}' == UpdateRegistration().json_dumps() + assert UpdateRegistration() == UpdateRegistration.json_loads(jstring) class RegistrationResourceTest(unittest.TestCase): @@ -324,11 +324,11 @@ class RegistrationResourceTest(unittest.TestCase): terms_of_service=mock.sentinel.terms_of_service) def test_to_partial_json(self): - self.assertEqual(self.regr.to_json(), { + assert self.regr.to_json() == { 'body': mock.sentinel.body, 'uri': mock.sentinel.uri, 'terms_of_service': mock.sentinel.terms_of_service, - }) + } class ChallengeResourceTest(unittest.TestCase): @@ -336,8 +336,8 @@ class ChallengeResourceTest(unittest.TestCase): def test_uri(self): from acme.messages import ChallengeResource - self.assertEqual('http://challb', ChallengeResource(body=mock.MagicMock( - uri='http://challb'), authzr_uri='http://authz').uri) + assert 'http://challb' == ChallengeResource(body=mock.MagicMock( + uri='http://challb'), authzr_uri='http://authz').uri class ChallengeBodyTest(unittest.TestCase): @@ -371,22 +371,22 @@ class ChallengeBodyTest(unittest.TestCase): } def test_encode(self): - self.assertEqual(self.challb.encode('uri'), self.challb.uri) + assert self.challb.encode('uri') == self.challb.uri def test_to_partial_json(self): - self.assertEqual(self.jobj_to, self.challb.to_partial_json()) + assert self.jobj_to == self.challb.to_partial_json() def test_from_json(self): from acme.messages import ChallengeBody - self.assertEqual(self.challb, ChallengeBody.from_json(self.jobj_from)) + assert self.challb == ChallengeBody.from_json(self.jobj_from) def test_from_json_hashable(self): from acme.messages import ChallengeBody hash(ChallengeBody.from_json(self.jobj_from)) def test_proxy(self): - self.assertEqual(jose.b64decode( - 'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA'), self.challb.token) + assert jose.b64decode( + 'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA') == self.challb.token class AuthorizationTest(unittest.TestCase): @@ -434,7 +434,7 @@ class AuthorizationResourceTest(unittest.TestCase): authzr = AuthorizationResource( uri=mock.sentinel.uri, body=mock.sentinel.body) - self.assertIsInstance(authzr, jose.JSONDeSerializable) + assert isinstance(authzr, jose.JSONDeSerializable) class CertificateRequestTest(unittest.TestCase): @@ -445,10 +445,9 @@ class CertificateRequestTest(unittest.TestCase): self.req = CertificateRequest(csr=CSR) def test_json_de_serializable(self): - self.assertIsInstance(self.req, jose.JSONDeSerializable) + assert isinstance(self.req, jose.JSONDeSerializable) from acme.messages import CertificateRequest - self.assertEqual( - self.req, CertificateRequest.from_json(self.req.to_json())) + assert self.req == CertificateRequest.from_json(self.req.to_json()) class CertificateResourceTest(unittest.TestCase): @@ -461,10 +460,9 @@ class CertificateResourceTest(unittest.TestCase): cert_chain_uri=mock.sentinel.cert_chain_uri) def test_json_de_serializable(self): - self.assertIsInstance(self.certr, jose.JSONDeSerializable) + assert isinstance(self.certr, jose.JSONDeSerializable) from acme.messages import CertificateResource - self.assertEqual( - self.certr, CertificateResource.from_json(self.certr.to_json())) + assert self.certr == CertificateResource.from_json(self.certr.to_json()) class RevocationTest(unittest.TestCase): @@ -488,11 +486,11 @@ class OrderResourceTest(unittest.TestCase): body=mock.sentinel.body, uri=mock.sentinel.uri) def test_to_partial_json(self): - self.assertEqual(self.regr.to_json(), { + assert self.regr.to_json() == { 'body': mock.sentinel.body, 'uri': mock.sentinel.uri, 'authorizations': None, - }) + } class NewOrderTest(unittest.TestCase): @@ -504,9 +502,9 @@ class NewOrderTest(unittest.TestCase): identifiers=mock.sentinel.identifiers) def test_to_partial_json(self): - self.assertEqual(self.reg.to_json(), { + assert self.reg.to_json() == { 'identifiers': mock.sentinel.identifiers, - }) + } class JWSPayloadRFC8555Compliant(unittest.TestCase): @@ -518,7 +516,7 @@ class JWSPayloadRFC8555Compliant(unittest.TestCase): jobj = new_order.json_dumps(indent=2).encode() # RFC8555 states that JWS bodies must not have a resource field. - self.assertEqual(jobj, b'{}') + assert jobj == b'{}' if __name__ == '__main__': diff --git a/acme/tests/standalone_test.py b/acme/tests/standalone_test.py index f9bc0c58c..4fcdceb57 100644 --- a/acme/tests/standalone_test.py +++ b/acme/tests/standalone_test.py @@ -59,14 +59,13 @@ class HTTP01ServerTest(unittest.TestCase): def test_index(self): response = requests.get( 'http://localhost:{0}'.format(self.port), verify=False) - self.assertEqual( - response.text, 'ACME client standalone challenge solver') - self.assertTrue(response.ok) + assert response.text == 'ACME client standalone challenge solver' + assert response.ok def test_404(self): response = requests.get( 'http://localhost:{0}/foo'.format(self.port), verify=False) - self.assertEqual(response.status_code, http_client.NOT_FOUND) + assert response.status_code == http_client.NOT_FOUND def _test_http01(self, add): chall = challenges.HTTP01(token=(b'x' * 16)) @@ -82,10 +81,10 @@ class HTTP01ServerTest(unittest.TestCase): port=self.port) def test_http01_found(self): - self.assertTrue(self._test_http01(add=True)) + assert self._test_http01(add=True) def test_http01_not_found(self): - self.assertFalse(self._test_http01(add=False)) + assert not self._test_http01(add=False) def test_timely_shutdown(self): from acme.standalone import HTTP01Server @@ -107,7 +106,7 @@ class HTTP01ServerTest(unittest.TestCase): # may raise error because socket could already be closed pass - self.assertFalse(is_hung, msg='Server shutdown should not be hung') + assert not is_hung, 'Server shutdown should not be hung' @unittest.skipIf(not challenges.TLSALPN01.is_supported(), "pyOpenSSL too old") @@ -150,14 +149,12 @@ class TLSALPN01ServerTest(unittest.TestCase): b'localhost', host=host, port=port, timeout=1, alpn_protocols=[b"acme-tls/1"]) # Expect challenge cert when connecting with ALPN. - self.assertEqual( - jose.ComparableX509(cert), + assert jose.ComparableX509(cert) == \ jose.ComparableX509(self.challenge_certs[b'localhost'][1]) - ) def test_bad_alpn(self): host, port = self.server.socket.getsockname()[:2] - with self.assertRaises(errors.Error): + with pytest.raises(errors.Error): crypto_util.probe_sni( b'localhost', host=host, port=port, timeout=1, alpn_protocols=[b"bad-alpn"]) @@ -196,12 +193,12 @@ class BaseDualNetworkedServersTest(unittest.TestCase): mock_bind.side_effect = socket.error(EADDRINUSE, "Fake addr in use error") - with self.assertRaises(socket.error) as em: + with pytest.raises(socket.error) as exc_info: BaseDualNetworkedServers( BaseDualNetworkedServersTest.SingleProtocolServer, ('', 0), socketserver.BaseRequestHandler) - self.assertEqual(em.exception.errno, EADDRINUSE) + assert exc_info.value.errno == EADDRINUSE def test_ports_equal(self): from acme.standalone import BaseDualNetworkedServers @@ -215,7 +212,7 @@ class BaseDualNetworkedServersTest(unittest.TestCase): for sockname in socknames: port = sockname[1] if prev_port: - self.assertEqual(prev_port, port) + assert prev_port == port prev_port = port @@ -239,14 +236,13 @@ class HTTP01DualNetworkedServersTest(unittest.TestCase): def test_index(self): response = requests.get( 'http://localhost:{0}'.format(self.port), verify=False) - self.assertEqual( - response.text, 'ACME client standalone challenge solver') - self.assertTrue(response.ok) + assert response.text == 'ACME client standalone challenge solver' + assert response.ok def test_404(self): response = requests.get( 'http://localhost:{0}/foo'.format(self.port), verify=False) - self.assertEqual(response.status_code, http_client.NOT_FOUND) + assert response.status_code == http_client.NOT_FOUND def _test_http01(self, add): chall = challenges.HTTP01(token=(b'x' * 16)) @@ -262,10 +258,10 @@ class HTTP01DualNetworkedServersTest(unittest.TestCase): port=self.port) def test_http01_found(self): - self.assertTrue(self._test_http01(add=True)) + assert self._test_http01(add=True) def test_http01_not_found(self): - self.assertFalse(self._test_http01(add=False)) + assert not self._test_http01(add=False) if __name__ == "__main__": diff --git a/acme/tests/util_test.py b/acme/tests/util_test.py index 372694b67..8df47c5be 100644 --- a/acme/tests/util_test.py +++ b/acme/tests/util_test.py @@ -10,9 +10,9 @@ class MapKeysTest(unittest.TestCase): def test_it(self): from acme.util import map_keys - self.assertEqual({'a': 'b', 'c': 'd'}, - map_keys({'a': 'b', 'c': 'd'}, lambda key: key)) - self.assertEqual({2: 2, 4: 4}, map_keys({1: 2, 3: 4}, lambda x: x + 1)) + assert {'a': 'b', 'c': 'd'} == \ + map_keys({'a': 'b', 'c': 'd'}, lambda key: key) + assert {2: 2, 4: 4} == map_keys({1: 2, 3: 4}, lambda x: x + 1) if __name__ == '__main__': diff --git a/certbot-apache/tests/augeasnode_test.py b/certbot-apache/tests/augeasnode_test.py index 01ae35628..2e977c307 100644 --- a/certbot-apache/tests/augeasnode_test.py +++ b/certbot-apache/tests/augeasnode_test.py @@ -7,6 +7,7 @@ from certbot import errors from certbot_apache._internal import assertions from certbot_apache._internal import augeasparser import util +import pytest def _get_augeasnode_mock(filepath): @@ -41,14 +42,14 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- def test_save(self): with mock.patch('certbot_apache._internal.parser.ApacheParser.save') as mock_save: self.config.parser_root.save("A save message") - self.assertIs(mock_save.called, True) - self.assertEqual(mock_save.call_args[0][0], "A save message") + assert mock_save.called is True + assert mock_save.call_args[0][0] == "A save message" def test_unsaved_files(self): with mock.patch('certbot_apache._internal.parser.ApacheParser.unsaved_files') as mock_uf: mock_uf.return_value = ["first", "second"] files = self.config.parser_root.unsaved_files() - self.assertEqual(files, ["first", "second"]) + assert files == ["first", "second"] def test_get_block_node_name(self): from certbot_apache._internal.augeasparser import AugeasBlockNode @@ -67,26 +68,26 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- } for test in testcases: # pylint: disable=protected-access - self.assertEqual(block._aug_get_name(test), testcases[test]) + assert block._aug_get_name(test) == testcases[test] def test_find_blocks(self): blocks = self.config.parser_root.find_blocks("VirtualHost", exclude=False) - self.assertEqual(len(blocks), 12) + assert len(blocks) == 12 def test_find_blocks_case_insensitive(self): vhs = self.config.parser_root.find_blocks("VirtualHost") vhs2 = self.config.parser_root.find_blocks("viRtuAlHoST") - self.assertEqual(len(vhs), len(vhs2)) + assert len(vhs) == len(vhs2) def test_find_directive_found(self): directives = self.config.parser_root.find_directives("Listen") - self.assertEqual(len(directives), 1) - self.assertIs(directives[0].filepath.endswith("/apache2/ports.conf"), True) - self.assertEqual(directives[0].parameters, (u'80',)) + assert len(directives) == 1 + assert directives[0].filepath.endswith("/apache2/ports.conf") is True + assert directives[0].parameters == (u'80',) def test_find_directive_notfound(self): directives = self.config.parser_root.find_directives("Nonexistent") - self.assertEqual(len(directives), 0) + assert len(directives) == 0 def test_find_directive_from_block(self): blocks = self.config.parser_root.find_blocks("virtualhost") @@ -94,31 +95,31 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- for vh in blocks: if vh.filepath.endswith("sites-enabled/certbot.conf"): servername = vh.find_directives("servername") - self.assertEqual(servername[0].parameters[0], "certbot.demo") + assert servername[0].parameters[0] == "certbot.demo" found = True - self.assertIs(found, True) + assert found is True def test_find_comments(self): rootcomment = self.config.parser_root.find_comments( "This is the main Apache server configuration file. " ) - self.assertEqual(len(rootcomment), 1) - self.assertIs(rootcomment[0].filepath.endswith( + assert len(rootcomment) == 1 + assert rootcomment[0].filepath.endswith( "debian_apache_2_4/multiple_vhosts/apache2/apache2.conf" - ), True) + ) is True def test_set_parameters(self): servernames = self.config.parser_root.find_directives("servername") names: List[str] = [] for servername in servernames: names += servername.parameters - self.assertNotIn("going_to_set_this", names) + assert "going_to_set_this" not in names servernames[0].set_parameters(["something", "going_to_set_this"]) servernames = self.config.parser_root.find_directives("servername") names = [] for servername in servernames: names += servername.parameters - self.assertIn("going_to_set_this", names) + assert "going_to_set_this" in names def test_set_parameters_atinit(self): from certbot_apache._internal.augeasparser import AugeasDirectiveNode @@ -131,11 +132,9 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- ancestor=assertions.PASS, metadata=servernames[0].metadata ) - self.assertIs(mock_set.called, True) - self.assertEqual( - mock_set.call_args_list[0][0][0], + assert mock_set.called is True + assert mock_set.call_args_list[0][0][0] == \ ["test", "setting", "these"] - ) def test_set_parameters_delete(self): # Set params @@ -148,48 +147,43 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- found = False for servername in servernames: if "thisshouldnotexistpreviously" in servername.parameters: - self.assertEqual(len(servername.parameters), 3) + assert len(servername.parameters) == 3 servername.set_parameters(["thisshouldnotexistpreviously"]) found = True - self.assertIs(found, True) + assert found is True # Verify params servernames = self.config.parser_root.find_directives("servername") found = False for servername in servernames: if "thisshouldnotexistpreviously" in servername.parameters: - self.assertEqual(len(servername.parameters), 1) + assert len(servername.parameters) == 1 servername.set_parameters(["thisshouldnotexistpreviously"]) found = True - self.assertIs(found, True) + assert found is True def test_add_child_comment(self): newc = self.config.parser_root.add_child_comment("The content") comments = self.config.parser_root.find_comments("The content") - self.assertEqual(len(comments), 1) - self.assertEqual( - newc.metadata["augeaspath"], + assert len(comments) == 1 + assert newc.metadata["augeaspath"] == \ comments[0].metadata["augeaspath"] - ) - self.assertEqual(newc.comment, comments[0].comment) + assert newc.comment == comments[0].comment def test_delete_child(self): listens = self.config.parser_root.find_directives("Listen") - self.assertEqual(len(listens), 1) + assert len(listens) == 1 self.config.parser_root.delete_child(listens[0]) listens = self.config.parser_root.find_directives("Listen") - self.assertEqual(len(listens), 0) + assert len(listens) == 0 def test_delete_child_not_found(self): listen = self.config.parser_root.find_directives("Listen")[0] listen.metadata["augeaspath"] = "/files/something/nonexistent" - self.assertRaises( - errors.PluginError, - self.config.parser_root.delete_child, - listen - ) + with pytest.raises(errors.PluginError): + self.config.parser_root.delete_child(listen) def test_add_child_block(self): nb = self.config.parser_root.add_child_block( @@ -197,11 +191,9 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- ["first", "second"] ) rpath, _, directive = nb.metadata["augeaspath"].rpartition("/") - self.assertEqual( - rpath, + assert rpath == \ self.config.parser_root.metadata["augeaspath"] - ) - self.assertIs(directive.startswith("NewBlock"), True) + assert directive.startswith("NewBlock") is True def test_add_child_block_beginning(self): self.config.parser_root.add_child_block( @@ -212,7 +204,7 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- root_path = self.config.parser_root.metadata["augeaspath"] # Get first child first = parser.aug.match("{}/*[1]".format(root_path)) - self.assertIs(first[0].endswith("Beginning"), True) + assert first[0].endswith("Beginning") is True def test_add_child_block_append(self): self.config.parser_root.add_child_block( @@ -222,7 +214,7 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- root_path = self.config.parser_root.metadata["augeaspath"] # Get last child last = parser.aug.match("{}/*[last()]".format(root_path)) - self.assertIs(last[0].endswith("VeryLast"), True) + assert last[0].endswith("VeryLast") is True def test_add_child_block_append_alt(self): self.config.parser_root.add_child_block( @@ -233,7 +225,7 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- root_path = self.config.parser_root.metadata["augeaspath"] # Get last child last = parser.aug.match("{}/*[last()]".format(root_path)) - self.assertIs(last[0].endswith("VeryLastAlt"), True) + assert last[0].endswith("VeryLastAlt") is True def test_add_child_block_middle(self): self.config.parser_root.add_child_block( @@ -244,20 +236,20 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- root_path = self.config.parser_root.metadata["augeaspath"] # Augeas indices start at 1 :( middle = parser.aug.match("{}/*[6]".format(root_path)) - self.assertIs(middle[0].endswith("Middle"), True) + assert middle[0].endswith("Middle") is True def test_add_child_block_existing_name(self): parser = self.config.parser_root.parser root_path = self.config.parser_root.metadata["augeaspath"] # There already exists a single VirtualHost in the base config new_block = parser.aug.match("{}/VirtualHost[2]".format(root_path)) - self.assertEqual(len(new_block), 0) + assert len(new_block) == 0 vh = self.config.parser_root.add_child_block( "VirtualHost", ) new_block = parser.aug.match("{}/VirtualHost[2]".format(root_path)) - self.assertEqual(len(new_block), 1) - self.assertIs(vh.metadata["augeaspath"].endswith("VirtualHost[2]"), True) + assert len(new_block) == 1 + assert vh.metadata["augeaspath"].endswith("VirtualHost[2]") is True def test_node_init_error_bad_augeaspath(self): from certbot_apache._internal.augeasparser import AugeasBlockNode @@ -270,11 +262,8 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- "augeaspath": "/files/path/endswith/slash/" } } - self.assertRaises( - errors.PluginError, - AugeasBlockNode, - **parameters - ) + with pytest.raises(errors.PluginError): + AugeasBlockNode(**parameters) def test_node_init_error_missing_augeaspath(self): from certbot_apache._internal.augeasparser import AugeasBlockNode @@ -286,11 +275,8 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- "augeasparser": mock.Mock(), } } - self.assertRaises( - errors.PluginError, - AugeasBlockNode, - **parameters - ) + with pytest.raises(errors.PluginError): + AugeasBlockNode(**parameters) def test_add_child_directive(self): self.config.parser_root.add_child_directive( @@ -299,21 +285,18 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- position=0 ) dirs = self.config.parser_root.find_directives("ThisWasAdded") - self.assertEqual(len(dirs), 1) - self.assertEqual(dirs[0].parameters, ("with", "parameters")) + assert len(dirs) == 1 + assert dirs[0].parameters == ("with", "parameters") # The new directive was added to the very first line of the config - self.assertIs(dirs[0].metadata["augeaspath"].endswith("[1]"), True) + assert dirs[0].metadata["augeaspath"].endswith("[1]") is True def test_add_child_directive_exception(self): - self.assertRaises( - errors.PluginError, - self.config.parser_root.add_child_directive, - "ThisRaisesErrorBecauseMissingParameters" - ) + with pytest.raises(errors.PluginError): + self.config.parser_root.add_child_directive("ThisRaisesErrorBecauseMissingParameters") def test_parsed_paths(self): paths = self.config.parser_root.parsed_paths() - self.assertEqual(len(paths), 6) + assert len(paths) == 6 def test_find_ancestors(self): vhsblocks = self.config.parser_root.find_blocks("VirtualHost") @@ -322,16 +305,16 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- for vh in vhsblocks: if "/macro/" in vh.metadata["augeaspath"].lower(): ancs = vh.find_ancestors("Macro") - self.assertEqual(len(ancs), 1) + assert len(ancs) == 1 macro_test = True else: ancs = vh.find_ancestors("Macro") - self.assertEqual(len(ancs), 0) + assert len(ancs) == 0 nonmacro_test = True - self.assertIs(macro_test, True) - self.assertIs(nonmacro_test, True) + assert macro_test is True + assert nonmacro_test is True def test_find_ancestors_bad_path(self): self.config.parser_root.metadata["augeaspath"] = "" ancs = self.config.parser_root.find_ancestors("Anything") - self.assertEqual(len(ancs), 0) + assert len(ancs) == 0 diff --git a/certbot-apache/tests/autohsts_test.py b/certbot-apache/tests/autohsts_test.py index b2e071695..48e4f7bf9 100644 --- a/certbot-apache/tests/autohsts_test.py +++ b/certbot-apache/tests/autohsts_test.py @@ -46,14 +46,13 @@ class AutoHSTSTest(util.ApacheTest): self.config.parser.modules.pop("headers_module", None) self.config.parser.modules.pop("mod_header.c", None) self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"]) - self.assertIs(mock_enable.called, True) + assert mock_enable.called is True @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart") def test_autohsts_deploy_already_exists(self, _restart): self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"]) - self.assertRaises(errors.PluginEnhancementAlreadyPresent, - self.config.enable_autohsts, - mock.MagicMock(), ["ocspvhost.com"]) + with pytest.raises(errors.PluginEnhancementAlreadyPresent): + self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"]) @mock.patch("certbot_apache._internal.constants.AUTOHSTS_FREQ", 0) @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart") @@ -66,14 +65,14 @@ class AutoHSTSTest(util.ApacheTest): self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"]) # Verify initial value - self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path), - initial_val) + assert self.get_autohsts_value(self.vh_truth[7].path) == \ + initial_val # Increase self.config.update_autohsts(mock.MagicMock()) # Verify increased value - self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path), - inc_val) - self.assertIs(mock_prepare.called, True) + assert self.get_autohsts_value(self.vh_truth[7].path) == \ + inc_val + assert mock_prepare.called is True @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart") @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._autohsts_increase") @@ -82,12 +81,12 @@ class AutoHSTSTest(util.ApacheTest): initial_val = maxage.format(constants.AUTOHSTS_STEPS[0]) self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"]) # Verify initial value - self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path), - initial_val) + assert self.get_autohsts_value(self.vh_truth[7].path) == \ + initial_val self.config.update_autohsts(mock.MagicMock()) # Freq not patched, so value shouldn't increase - self.assertIs(mock_increase.called, False) + assert mock_increase.called is False @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart") @@ -99,9 +98,8 @@ class AutoHSTSTest(util.ApacheTest): self.vh_truth[7].path) dir_loc = "/".join(dir_locs[0].split("/")[:-1]) self.config.parser.aug.remove(dir_loc) - self.assertRaises(errors.PluginError, - self.config.update_autohsts, - mock.MagicMock()) + with pytest.raises(errors.PluginError): + self.config.update_autohsts(mock.MagicMock()) @mock.patch("certbot_apache._internal.constants.AUTOHSTS_FREQ", 0) @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart") @@ -114,49 +112,48 @@ class AutoHSTSTest(util.ApacheTest): for i in range(len(constants.AUTOHSTS_STEPS)-1): # Ensure that value is not made permanent prematurely self.config.deploy_autohsts(mock_lineage) - self.assertNotEqual(self.get_autohsts_value(self.vh_truth[7].path), - max_val) + assert self.get_autohsts_value(self.vh_truth[7].path) != \ + max_val self.config.update_autohsts(mock.MagicMock()) # Value should match pre-permanent increment step cur_val = maxage.format(constants.AUTOHSTS_STEPS[i+1]) - self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path), - cur_val) + assert self.get_autohsts_value(self.vh_truth[7].path) == \ + cur_val # Ensure that the value is raised to max - self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path), - maxage.format(constants.AUTOHSTS_STEPS[-1])) + assert self.get_autohsts_value(self.vh_truth[7].path) == \ + maxage.format(constants.AUTOHSTS_STEPS[-1]) # Make permanent self.config.deploy_autohsts(mock_lineage) - self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path), - max_val) + assert self.get_autohsts_value(self.vh_truth[7].path) == \ + max_val def test_autohsts_update_noop(self): with mock.patch("time.time") as mock_time: # Time mock is used to make sure that the execution does not # continue when no autohsts entries exist in pluginstorage self.config.update_autohsts(mock.MagicMock()) - self.assertIs(mock_time.called, False) + assert mock_time.called is False def test_autohsts_make_permanent_noop(self): self.config.storage.put = mock.MagicMock() self.config.deploy_autohsts(mock.MagicMock()) # Make sure that the execution does not continue when no entries in store - self.assertIs(self.config.storage.put.called, False) + assert self.config.storage.put.called is False @mock.patch("certbot_apache._internal.display_ops.select_vhost") def test_autohsts_no_ssl_vhost(self, mock_select): mock_select.return_value = self.vh_truth[0] with mock.patch("certbot_apache._internal.configurator.logger.error") as mock_log: - self.assertRaises(errors.PluginError, - self.config.enable_autohsts, - mock.MagicMock(), "invalid.example.com") - self.assertIn("Certbot was not able to find SSL", mock_log.call_args[0][0]) + with pytest.raises(errors.PluginError): + self.config.enable_autohsts(mock.MagicMock(), "invalid.example.com") + assert "Certbot was not able to find SSL" in mock_log.call_args[0][0] @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart") @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.add_vhost_id") def test_autohsts_dont_enhance_twice(self, mock_id, _restart): mock_id.return_value = "1234567" self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com", "ocspvhost.com"]) - self.assertEqual(mock_id.call_count, 1) + assert mock_id.call_count == 1 def test_autohsts_remove_orphaned(self): # pylint: disable=protected-access @@ -165,11 +162,11 @@ class AutoHSTSTest(util.ApacheTest): self.config._autohsts_save_state() self.config.update_autohsts(mock.MagicMock()) - self.assertNotIn("orphan_id", self.config._autohsts) + assert "orphan_id" not in self.config._autohsts # Make sure it's removed from the pluginstorage file as well self.config._autohsts = None self.config._autohsts_fetch_state() - self.assertFalse(self.config._autohsts) + assert not self.config._autohsts def test_autohsts_make_permanent_vhost_not_found(self): # pylint: disable=protected-access @@ -178,8 +175,8 @@ class AutoHSTSTest(util.ApacheTest): self.config._autohsts_save_state() with mock.patch("certbot_apache._internal.configurator.logger.error") as mock_log: self.config.deploy_autohsts(mock.MagicMock()) - self.assertIs(mock_log.called, True) - self.assertIn("VirtualHost with id orphan_id was not", mock_log.call_args[0][0]) + assert mock_log.called is True + assert "VirtualHost with id orphan_id was not" in mock_log.call_args[0][0] if __name__ == "__main__": diff --git a/certbot-apache/tests/centos_test.py b/certbot-apache/tests/centos_test.py index 5aba89388..dd2108de1 100644 --- a/certbot-apache/tests/centos_test.py +++ b/certbot-apache/tests/centos_test.py @@ -51,7 +51,7 @@ class FedoraRestartTest(util.ApacheTest): self.temp_dir, "centos7_apache/apache") def _run_fedora_test(self): - self.assertIsInstance(self.config, override_centos.CentOSConfigurator) + assert isinstance(self.config, override_centos.CentOSConfigurator) with mock.patch("certbot.util.get_os_info") as mock_info: mock_info.return_value = ["fedora", "28"] self.config.config_test() @@ -62,8 +62,8 @@ class FedoraRestartTest(util.ApacheTest): mock_test.side_effect = errors.MisconfigurationError with mock.patch("certbot.util.get_os_info") as mock_info: mock_info.return_value = ["not_fedora"] - self.assertRaises(errors.MisconfigurationError, - self.config.config_test) + with pytest.raises(errors.MisconfigurationError): + self.config.config_test() def test_fedora_restart_error(self): c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test" @@ -72,8 +72,8 @@ class FedoraRestartTest(util.ApacheTest): mock_test.side_effect = [errors.MisconfigurationError, ''] with mock.patch("certbot.util.run_script") as mock_run: mock_run.side_effect = errors.SubprocessError - self.assertRaises(errors.MisconfigurationError, - self._run_fedora_test) + with pytest.raises(errors.MisconfigurationError): + self._run_fedora_test() def test_fedora_restart(self): c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test" @@ -82,9 +82,9 @@ class FedoraRestartTest(util.ApacheTest): # First call raises error, second doesn't mock_test.side_effect = [errors.MisconfigurationError, ''] self._run_fedora_test() - self.assertEqual(mock_test.call_count, 2) - self.assertEqual(mock_run.call_args[0][0], - ['systemctl', 'restart', 'httpd']) + assert mock_test.call_count == 2 + assert mock_run.call_args[0][0] == \ + ['systemctl', 'restart', 'httpd'] class UseCorrectApacheExecutableTest(util.ApacheTest): @@ -105,15 +105,15 @@ class UseCorrectApacheExecutableTest(util.ApacheTest): config = util.get_apache_configurator( self.config_path, self.vhost_path, self.config_dir, self.work_dir, os_info="centos") - self.assertEqual(config.options.ctl, "apachectl") - self.assertEqual(config.options.bin, "httpd") - self.assertEqual(config.options.version_cmd, ["apachectl", "-v"]) - self.assertEqual(config.options.restart_cmd, ["apachectl", "graceful"]) - self.assertEqual(config.options.restart_cmd_alt, ["apachectl", "restart"]) - self.assertEqual(config.options.conftest_cmd, ["apachectl", "configtest"]) - self.assertEqual(config.options.get_defines_cmd, ["apachectl", "-t", "-D", "DUMP_RUN_CFG"]) - self.assertEqual(config.options.get_includes_cmd, ["apachectl", "-t", "-D", "DUMP_INCLUDES"]) - self.assertEqual(config.options.get_modules_cmd, ["apachectl", "-t", "-D", "DUMP_MODULES"]) + assert config.options.ctl == "apachectl" + assert config.options.bin == "httpd" + assert config.options.version_cmd == ["apachectl", "-v"] + assert config.options.restart_cmd == ["apachectl", "graceful"] + assert config.options.restart_cmd_alt == ["apachectl", "restart"] + assert config.options.conftest_cmd == ["apachectl", "configtest"] + assert config.options.get_defines_cmd == ["apachectl", "-t", "-D", "DUMP_RUN_CFG"] + assert config.options.get_includes_cmd == ["apachectl", "-t", "-D", "DUMP_INCLUDES"] + assert config.options.get_modules_cmd == ["apachectl", "-t", "-D", "DUMP_MODULES"] @mock.patch("certbot.util.get_os_info") def test_new_rhel_derived(self, mock_get_os_info): @@ -122,15 +122,15 @@ class UseCorrectApacheExecutableTest(util.ApacheTest): config = util.get_apache_configurator( self.config_path, self.vhost_path, self.config_dir, self.work_dir, os_info=os_info[0]) - self.assertEqual(config.options.ctl, "apachectl") - self.assertEqual(config.options.bin, "httpd") - self.assertEqual(config.options.version_cmd, ["httpd", "-v"]) - self.assertEqual(config.options.restart_cmd, ["apachectl", "graceful"]) - self.assertEqual(config.options.restart_cmd_alt, ["apachectl", "restart"]) - self.assertEqual(config.options.conftest_cmd, ["apachectl", "configtest"]) - self.assertEqual(config.options.get_defines_cmd, ["httpd", "-t", "-D", "DUMP_RUN_CFG"]) - self.assertEqual(config.options.get_includes_cmd, ["httpd", "-t", "-D", "DUMP_INCLUDES"]) - self.assertEqual(config.options.get_modules_cmd, ["httpd", "-t", "-D", "DUMP_MODULES"]) + assert config.options.ctl == "apachectl" + assert config.options.bin == "httpd" + assert config.options.version_cmd == ["httpd", "-v"] + assert config.options.restart_cmd == ["apachectl", "graceful"] + assert config.options.restart_cmd_alt == ["apachectl", "restart"] + assert config.options.conftest_cmd == ["apachectl", "configtest"] + assert config.options.get_defines_cmd == ["httpd", "-t", "-D", "DUMP_RUN_CFG"] + assert config.options.get_includes_cmd == ["httpd", "-t", "-D", "DUMP_INCLUDES"] + assert config.options.get_modules_cmd == ["httpd", "-t", "-D", "DUMP_MODULES"] class MultipleVhostsTestCentOS(util.ApacheTest): @@ -154,7 +154,7 @@ class MultipleVhostsTestCentOS(util.ApacheTest): self.temp_dir, "centos7_apache/apache") def test_get_parser(self): - self.assertIsInstance(self.config.parser, override_centos.CentOSParser) + assert isinstance(self.config.parser, override_centos.CentOSParser) @mock.patch("certbot_apache._internal.apache_util._get_runtime_cfg") def test_opportunistic_httpd_runtime_parsing(self, mock_get): @@ -184,16 +184,16 @@ class MultipleVhostsTestCentOS(util.ApacheTest): mock_osi.return_value = ("centos", "9") self.config.parser.update_runtime_variables() - self.assertEqual(mock_get.call_count, 3) - self.assertEqual(len(self.config.parser.modules), 4) - self.assertEqual(len(self.config.parser.variables), 2) - self.assertIn("TEST2", self.config.parser.variables) - self.assertIn("mod_another.c", self.config.parser.modules) + assert mock_get.call_count == 3 + assert len(self.config.parser.modules) == 4 + assert len(self.config.parser.variables) == 2 + assert "TEST2" in self.config.parser.variables + assert "mod_another.c" in self.config.parser.modules def test_get_virtual_hosts(self): """Make sure all vhosts are being properly found.""" vhs = self.config.get_virtual_hosts() - self.assertEqual(len(vhs), 2) + assert len(vhs) == 2 found = 0 for vhost in vhs: @@ -203,7 +203,7 @@ class MultipleVhostsTestCentOS(util.ApacheTest): break else: raise Exception("Missed: %s" % vhost) # pragma: no cover - self.assertEqual(found, 2) + assert found == 2 @mock.patch("certbot_apache._internal.apache_util._get_runtime_cfg") def test_get_sysconfig_vars(self, mock_cfg): @@ -219,25 +219,26 @@ class MultipleVhostsTestCentOS(util.ApacheTest): mock_osi.return_value = ("centos", "9") self.config.parser.update_runtime_variables() - self.assertIn("mock_define", self.config.parser.variables) - self.assertIn("mock_define_too", self.config.parser.variables) - self.assertIn("mock_value", self.config.parser.variables) - self.assertEqual("TRUE", self.config.parser.variables["mock_value"]) - self.assertIn("MOCK_NOSEP", self.config.parser.variables) - self.assertEqual("NOSEP_VAL", self.config.parser.variables["NOSEP_TWO"]) + assert "mock_define" in self.config.parser.variables + assert "mock_define_too" in self.config.parser.variables + assert "mock_value" in self.config.parser.variables + assert "TRUE" == self.config.parser.variables["mock_value"] + assert "MOCK_NOSEP" in self.config.parser.variables + assert "NOSEP_VAL" == self.config.parser.variables["NOSEP_TWO"] @mock.patch("certbot_apache._internal.configurator.util.run_script") def test_alt_restart_works(self, mock_run_script): mock_run_script.side_effect = [None, errors.SubprocessError, None] self.config.restart() - self.assertEqual(mock_run_script.call_count, 3) + assert mock_run_script.call_count == 3 @mock.patch("certbot_apache._internal.configurator.util.run_script") def test_alt_restart_errors(self, mock_run_script): mock_run_script.side_effect = [None, errors.SubprocessError, errors.SubprocessError] - self.assertRaises(errors.MisconfigurationError, self.config.restart) + with pytest.raises(errors.MisconfigurationError): + self.config.restart() if __name__ == "__main__": diff --git a/certbot-apache/tests/complex_parsing_test.py b/certbot-apache/tests/complex_parsing_test.py index c26a65b64..ef06d94d1 100644 --- a/certbot-apache/tests/complex_parsing_test.py +++ b/certbot-apache/tests/complex_parsing_test.py @@ -41,51 +41,49 @@ class ComplexParserTest(util.ParserTest): """Note: This may also fail do to Include conf-enabled/ syntax.""" matches = self.parser.find_dir("TestArgsDirective") - self.assertEqual(len(self.parser.filter_args_num(matches, 1)), 3) - self.assertEqual(len(self.parser.filter_args_num(matches, 2)), 2) - self.assertEqual(len(self.parser.filter_args_num(matches, 3)), 1) + assert len(self.parser.filter_args_num(matches, 1)) == 3 + assert len(self.parser.filter_args_num(matches, 2)) == 2 + assert len(self.parser.filter_args_num(matches, 3)) == 1 def test_basic_variable_parsing(self): matches = self.parser.find_dir("TestVariablePort") - self.assertEqual(len(matches), 1) - self.assertEqual(self.parser.get_arg(matches[0]), "1234") + assert len(matches) == 1 + assert self.parser.get_arg(matches[0]) == "1234" def test_basic_variable_parsing_quotes(self): matches = self.parser.find_dir("TestVariablePortStr") - self.assertEqual(len(matches), 1) - self.assertEqual(self.parser.get_arg(matches[0]), "1234") + assert len(matches) == 1 + assert self.parser.get_arg(matches[0]) == "1234" def test_invalid_variable_parsing(self): del self.parser.variables["tls_port"] matches = self.parser.find_dir("TestVariablePort") - self.assertRaises( - errors.PluginError, self.parser.get_arg, matches[0]) + with pytest.raises(errors.PluginError): + self.parser.get_arg(matches[0]) def test_basic_ifdefine(self): - self.assertEqual(len(self.parser.find_dir("VAR_DIRECTIVE")), 2) - self.assertEqual(len(self.parser.find_dir("INVALID_VAR_DIRECTIVE")), 0) + assert len(self.parser.find_dir("VAR_DIRECTIVE")) == 2 + assert len(self.parser.find_dir("INVALID_VAR_DIRECTIVE")) == 0 def test_basic_ifmodule(self): - self.assertEqual(len(self.parser.find_dir("MOD_DIRECTIVE")), 2) - self.assertEqual( - len(self.parser.find_dir("INVALID_MOD_DIRECTIVE")), 0) + assert len(self.parser.find_dir("MOD_DIRECTIVE")) == 2 + assert len(self.parser.find_dir("INVALID_MOD_DIRECTIVE")) == 0 def test_nested(self): - self.assertEqual(len(self.parser.find_dir("NESTED_DIRECTIVE")), 3) - self.assertEqual( - len(self.parser.find_dir("INVALID_NESTED_DIRECTIVE")), 0) + assert len(self.parser.find_dir("NESTED_DIRECTIVE")) == 3 + assert len(self.parser.find_dir("INVALID_NESTED_DIRECTIVE")) == 0 def test_load_modules(self): """If only first is found, there is bad variable parsing.""" - self.assertIn("status_module", self.parser.modules) - self.assertIn("mod_status.c", self.parser.modules) + assert "status_module" in self.parser.modules + assert "mod_status.c" in self.parser.modules # This is in an IfDefine - self.assertIn("ssl_module", self.parser.modules) - self.assertIn("mod_ssl.c", self.parser.modules) + assert "ssl_module" in self.parser.modules + assert "mod_ssl.c" in self.parser.modules def verify_fnmatch(self, arg, hit=True): """Test if Include was correctly parsed.""" @@ -93,9 +91,9 @@ class ComplexParserTest(util.ParserTest): self.parser.add_dir(parser.get_aug_path(self.parser.loc["default"]), "Include", [arg]) if hit: - self.assertTrue(self.parser.find_dir("FNMATCH_DIRECTIVE")) + assert self.parser.find_dir("FNMATCH_DIRECTIVE") else: - self.assertFalse(self.parser.find_dir("FNMATCH_DIRECTIVE")) + assert not self.parser.find_dir("FNMATCH_DIRECTIVE") # NOTE: Only run one test per function otherwise you will have # inf recursion diff --git a/certbot-apache/tests/configurator_reverter_test.py b/certbot-apache/tests/configurator_reverter_test.py index b0ddacfed..21b1188e8 100644 --- a/certbot-apache/tests/configurator_reverter_test.py +++ b/certbot-apache/tests/configurator_reverter_test.py @@ -29,50 +29,53 @@ class ConfiguratorReverterTest(util.ApacheTest): def test_bad_save_checkpoint(self): self.config.reverter.add_to_checkpoint = mock.Mock(side_effect=errors.ReverterError) self.config.parser.add_dir(self.vh_truth[0].path, "Test", "bad_save_ckpt") - self.assertRaises(errors.PluginError, self.config.save) + with pytest.raises(errors.PluginError): + self.config.save() def test_bad_save_finalize_checkpoint(self): self.config.reverter.finalize_checkpoint = mock.Mock(side_effect=errors.ReverterError) self.config.parser.add_dir(self.vh_truth[0].path, "Test", "bad_save_ckpt") - self.assertRaises(errors.PluginError, self.config.save, "Title") + with pytest.raises(errors.PluginError): + self.config.save("Title") def test_finalize_save(self): mock_finalize = mock.Mock() self.config.reverter = mock_finalize self.config.save("Example Title") - self.assertTrue(mock_finalize.is_called) + assert mock_finalize.is_called def test_revert_challenge_config(self): mock_load = mock.Mock() self.config.parser.aug.load = mock_load self.config.revert_challenge_config() - self.assertEqual(mock_load.call_count, 1) + assert mock_load.call_count == 1 def test_revert_challenge_config_error(self): self.config.reverter.revert_temporary_config = mock.Mock( side_effect=errors.ReverterError) - self.assertRaises( - errors.PluginError, self.config.revert_challenge_config) + with pytest.raises(errors.PluginError): + self.config.revert_challenge_config() def test_rollback_checkpoints(self): mock_load = mock.Mock() self.config.parser.aug.load = mock_load self.config.rollback_checkpoints() - self.assertEqual(mock_load.call_count, 1) + assert mock_load.call_count == 1 def test_rollback_error(self): self.config.reverter.rollback_checkpoints = mock.Mock(side_effect=errors.ReverterError) - self.assertRaises(errors.PluginError, self.config.rollback_checkpoints) + with pytest.raises(errors.PluginError): + self.config.rollback_checkpoints() def test_recovery_routine_reload(self): mock_load = mock.Mock() self.config.parser.aug.load = mock_load self.config.recovery_routine() - self.assertEqual(mock_load.call_count, 1) + assert mock_load.call_count == 1 if __name__ == "__main__": diff --git a/certbot-apache/tests/configurator_test.py b/certbot-apache/tests/configurator_test.py index e9ac734f9..6b22ce8c7 100644 --- a/certbot-apache/tests/configurator_test.py +++ b/certbot-apache/tests/configurator_test.py @@ -54,8 +54,9 @@ class MultipleVhostsTest(util.ApacheTest): silly_path = {"PATH": "/tmp/nothingness2342"} mock_surgery.return_value = False with mock.patch.dict('os.environ', silly_path): - self.assertRaises(errors.NoInstallationError, self.config.prepare) - self.assertEqual(mock_surgery.call_count, 1) + with pytest.raises(errors.NoInstallationError): + self.config.prepare() + assert mock_surgery.call_count == 1 @mock.patch("certbot_apache._internal.parser.ApacheParser") @mock.patch("certbot_apache._internal.configurator.util.exe_exists") @@ -65,8 +66,8 @@ class MultipleVhostsTest(util.ApacheTest): self.config.config_test = mock.Mock() self.config.get_version = mock.Mock(return_value=(1, 1)) - self.assertRaises( - errors.NotSupportedError, self.config.prepare) + with pytest.raises(errors.NotSupportedError): + self.config.prepare() def test_prepare_locked(self): server_root = self.config.conf("server-root") @@ -82,8 +83,8 @@ class MultipleVhostsTest(util.ApacheTest): self.config.prepare() except errors.PluginError as err: err_msg = str(err) - self.assertIn("lock", err_msg) - self.assertIn(self.config.conf("server-root"), err_msg) + assert "lock" in err_msg + assert self.config.conf("server-root") in err_msg else: # pragma: no cover self.fail("Exception wasn't raised!") @@ -114,10 +115,10 @@ class MultipleVhostsTest(util.ApacheTest): found.add(call[0][0]) # Make sure that all (and only) the expected values exist - self.assertEqual(len(mock_add.call_args_list), len(found)) + assert len(mock_add.call_args_list) == len(found) for e in exp: with self.subTest(e=e): - self.assertIn(e, found) + assert e in found del os.environ["CERTBOT_DOCS"] @@ -131,19 +132,19 @@ class MultipleVhostsTest(util.ApacheTest): from certbot_apache._internal.entrypoint import OVERRIDE_CLASSES parameters = set(ApacheConfigurator.OS_DEFAULTS.__dict__.keys()) for cls in OVERRIDE_CLASSES.values(): - self.assertIs(parameters.issubset(set(cls.OS_DEFAULTS.__dict__.keys())), True) + assert parameters.issubset(set(cls.OS_DEFAULTS.__dict__.keys())) is True def test_constant(self): - self.assertIn("debian_apache_2_4/multiple_vhosts/apache", self.config.options.server_root) + assert "debian_apache_2_4/multiple_vhosts/apache" in self.config.options.server_root @certbot_util.patch_display_util() def test_get_all_names(self, mock_getutility): mock_utility = mock_getutility() mock_utility.notification = mock.MagicMock(return_value=True) names = self.config.get_all_names() - self.assertEqual(names, {"certbot.demo", "ocspvhost.com", "encryption-example.demo", + assert names == {"certbot.demo", "ocspvhost.com", "encryption-example.demo", "nonsym.link", "vhost.in.rootconf", "www.certbot.demo", - "duplicate.example.com"}) + "duplicate.example.com"} @certbot_util.patch_display_util() @mock.patch("certbot_apache._internal.configurator.socket.gethostbyaddr") @@ -161,15 +162,15 @@ class MultipleVhostsTest(util.ApacheTest): self.config.vhosts.append(vhost) names = self.config.get_all_names() - self.assertEqual(len(names), 9) - self.assertIn("zombo.com", names) - self.assertIn("google.com", names) - self.assertIn("certbot.demo", names) + assert len(names) == 9 + assert "zombo.com" in names + assert "google.com" in names + assert "certbot.demo" in names def test_get_bad_path(self): - self.assertEqual(apache_util.get_file_path(None), None) - self.assertEqual(apache_util.get_file_path("nonexistent"), None) - self.assertEqual(self.config._create_vhost("nonexistent"), None) # pylint: disable=protected-access + assert apache_util.get_file_path(None) == None + assert apache_util.get_file_path("nonexistent") == None + assert self.config._create_vhost("nonexistent") == None # pylint: disable=protected-access def test_get_aug_internal_path(self): from certbot_apache._internal.apache_util import get_internal_aug_path @@ -179,8 +180,7 @@ class MultipleVhostsTest(util.ApacheTest): "IfModule/VirtualHost"] for i, internal_path in enumerate(internal_paths): - self.assertEqual( - get_internal_aug_path(self.vh_truth[i].path), internal_path) + assert get_internal_aug_path(self.vh_truth[i].path) == internal_path def test_bad_servername_alias(self): ssl_vh1 = obj.VirtualHost( @@ -188,19 +188,19 @@ class MultipleVhostsTest(util.ApacheTest): True, False) # pylint: disable=protected-access self.config._add_servernames(ssl_vh1) - self.assertIsNone(self.config._add_servername_alias("oy_vey", ssl_vh1)) + assert self.config._add_servername_alias("oy_vey", ssl_vh1) is None def test_add_servernames_alias(self): self.config.parser.add_dir( self.vh_truth[2].path, "ServerAlias", ["*.le.co"]) # pylint: disable=protected-access self.config._add_servernames(self.vh_truth[2]) - self.assertEqual(self.vh_truth[2].get_names(), {"*.le.co", "ip-172-30-0-17"}) + assert self.vh_truth[2].get_names() == {"*.le.co", "ip-172-30-0-17"} def test_get_virtual_hosts(self): """Make sure all vhosts are being properly found.""" vhs = self.config.get_virtual_hosts() - self.assertEqual(len(vhs), 12) + assert len(vhs) == 12 found = 0 for vhost in vhs: @@ -211,7 +211,7 @@ class MultipleVhostsTest(util.ApacheTest): else: raise Exception("Missed: %s" % vhost) # pragma: no cover - self.assertEqual(found, 12) + assert found == 12 # Handle case of non-debian layout get_virtual_hosts with mock.patch( @@ -219,19 +219,18 @@ class MultipleVhostsTest(util.ApacheTest): ) as mock_conf: mock_conf.return_value = False vhs = self.config.get_virtual_hosts() - self.assertEqual(len(vhs), 12) + assert len(vhs) == 12 @mock.patch("certbot_apache._internal.display_ops.select_vhost") def test_choose_vhost_none_avail(self, mock_select): mock_select.return_value = None - self.assertRaises( - errors.PluginError, self.config.choose_vhost, "none.com") + with pytest.raises(errors.PluginError): + self.config.choose_vhost("none.com") @mock.patch("certbot_apache._internal.display_ops.select_vhost") def test_choose_vhost_select_vhost_ssl(self, mock_select): mock_select.return_value = self.vh_truth[1] - self.assertEqual( - self.vh_truth[1], self.config.choose_vhost("none.com")) + assert self.vh_truth[1] == self.config.choose_vhost("none.com") @mock.patch("certbot_apache._internal.display_ops.select_vhost") @mock.patch("certbot_apache._internal.obj.VirtualHost.conflicts") @@ -240,12 +239,11 @@ class MultipleVhostsTest(util.ApacheTest): mock_conf.return_value = False chosen_vhost = self.config.choose_vhost("none.com") self.vh_truth[0].aliases.add("none.com") - self.assertEqual( - self.vh_truth[0].get_names(), chosen_vhost.get_names()) + assert self.vh_truth[0].get_names() == chosen_vhost.get_names() # Make sure we go from HTTP -> HTTPS - self.assertIs(self.vh_truth[0].ssl, False) - self.assertIs(chosen_vhost.ssl, True) + assert self.vh_truth[0].ssl is False + assert chosen_vhost.ssl is True @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._find_best_vhost") @mock.patch("certbot_apache._internal.parser.ApacheParser.add_dir") @@ -254,13 +252,13 @@ class MultipleVhostsTest(util.ApacheTest): ret_vh.enabled = False mock_find.return_value = self.vh_truth[8] self.config.choose_vhost("whatever.com") - self.assertIs(mock_add.called, True) + assert mock_add.called is True @mock.patch("certbot_apache._internal.display_ops.select_vhost") def test_choose_vhost_select_vhost_with_temp(self, mock_select): mock_select.return_value = self.vh_truth[0] chosen_vhost = self.config.choose_vhost("none.com", create_if_no_ssl=False) - self.assertEqual(self.vh_truth[0], chosen_vhost) + assert self.vh_truth[0] == chosen_vhost @mock.patch("certbot_apache._internal.display_ops.select_vhost") def test_choose_vhost_select_vhost_conflicting_non_ssl(self, mock_select): @@ -270,14 +268,14 @@ class MultipleVhostsTest(util.ApacheTest): True, True) self.config.vhosts.append(conflicting_vhost) - self.assertRaises( - errors.PluginError, self.config.choose_vhost, "none.com") + with pytest.raises(errors.PluginError): + self.config.choose_vhost("none.com") def test_find_best_http_vhost_default(self): vh = obj.VirtualHost( "fp", "ap", {obj.Addr.fromstring("_default_:80")}, False, True) self.config.vhosts = [vh] - self.assertEqual(self.config.find_best_http_vhost("foo.bar", False), vh) + assert self.config.find_best_http_vhost("foo.bar", False) == vh def test_find_best_http_vhost_port(self): port = "8080" @@ -285,21 +283,21 @@ class MultipleVhostsTest(util.ApacheTest): "fp", "ap", {obj.Addr.fromstring("*:" + port)}, False, True, "encryption-example.demo") self.config.vhosts.append(vh) - self.assertEqual(self.config.find_best_http_vhost("foo.bar", False, port), vh) + assert self.config.find_best_http_vhost("foo.bar", False, port) == vh def test_findbest_continues_on_short_domain(self): # pylint: disable=protected-access - self.assertIsNone(self.config._find_best_vhost("purple.com")) + assert self.config._find_best_vhost("purple.com") is None def test_findbest_continues_on_long_domain(self): # pylint: disable=protected-access - self.assertIsNone(self.config._find_best_vhost("green.red.purple.com")) + assert self.config._find_best_vhost("green.red.purple.com") is None def test_find_best_vhost(self): # pylint: disable=protected-access - self.assertEqual(self.vh_truth[3], self.config._find_best_vhost("certbot.demo")) - self.assertEqual(self.vh_truth[0], self.config._find_best_vhost("encryption-example.demo")) - self.assertEqual(self.config._find_best_vhost("does-not-exist.com"), None) + assert self.vh_truth[3] == self.config._find_best_vhost("certbot.demo") + assert self.vh_truth[0] == self.config._find_best_vhost("encryption-example.demo") + assert self.config._find_best_vhost("does-not-exist.com") == None def test_find_best_vhost_variety(self): # pylint: disable=protected-access @@ -308,7 +306,7 @@ class MultipleVhostsTest(util.ApacheTest): obj.Addr(("zombo.com",))}, True, False) self.config.vhosts.append(ssl_vh) - self.assertEqual(self.config._find_best_vhost("zombo.com"), ssl_vh) + assert self.config._find_best_vhost("zombo.com") == ssl_vh def test_find_best_vhost_default(self): # pylint: disable=protected-access @@ -320,14 +318,13 @@ class MultipleVhostsTest(util.ApacheTest): "ocspvhost.com", "vhost.in.rootconf"] and "*.blue.purple.com" not in vh.aliases ] - self.assertEqual( - self.config._find_best_vhost("encryption-example.demo"), - self.vh_truth[2]) + assert self.config._find_best_vhost("encryption-example.demo") == \ + self.vh_truth[2] def test_non_default_vhosts(self): # pylint: disable=protected-access vhosts = self.config._non_default_vhosts(self.config.vhosts) - self.assertEqual(len(vhosts), 10) + assert len(vhosts) == 10 @mock.patch('certbot_apache._internal.configurator.display_util.notify') def test_deploy_cert_enable_new_vhost(self, unused_mock_notify): @@ -337,11 +334,11 @@ class MultipleVhostsTest(util.ApacheTest): self.config.parser.modules["mod_ssl.c"] = None self.config.parser.modules["socache_shmcb_module"] = None - self.assertIs(ssl_vhost.enabled, False) + assert ssl_vhost.enabled is False self.config.deploy_cert( "encryption-example.demo", "example/cert.pem", "example/key.pem", "example/cert_chain.pem", "example/fullchain.pem") - self.assertIs(ssl_vhost.enabled, True) + assert ssl_vhost.enabled is True def test_no_duplicate_include(self): def mock_find_dir(directive, argument, _): @@ -358,7 +355,7 @@ class MultipleVhostsTest(util.ApacheTest): if a[0][1] == "Include" and a[0][2] == self.config.mod_ssl_conf: tried_to_add = True # Include should be added, find_dir is not patched, and returns falsy - self.assertIs(tried_to_add, True) + assert tried_to_add is True self.config.parser.find_dir = mock_find_dir mock_add.reset_mock() @@ -387,16 +384,12 @@ class MultipleVhostsTest(util.ApacheTest): f_args.append(self.config.parser.get_arg(d)) return f_args # Verify that the dummy directives do not exist - self.assertNotIn( - "insert_cert_file_path", find_args(vhostpath, "SSLCertificateFile")) - self.assertNotIn( - "insert_key_file_path", find_args(vhostpath, "SSLCertificateKeyFile")) + assert "insert_cert_file_path" not in find_args(vhostpath, "SSLCertificateFile") + assert "insert_key_file_path" not in find_args(vhostpath, "SSLCertificateKeyFile") orig_add_dummy(vhostpath) # Verify that the dummy directives exist - self.assertIn( - "insert_cert_file_path", find_args(vhostpath, "SSLCertificateFile")) - self.assertIn( - "insert_key_file_path", find_args(vhostpath, "SSLCertificateKeyFile")) + assert "insert_cert_file_path" in find_args(vhostpath, "SSLCertificateFile") + assert "insert_key_file_path" in find_args(vhostpath, "SSLCertificateKeyFile") # pylint: disable=protected-access self.config._add_dummy_ssl_directives = mock_add_dummy_ssl @@ -408,8 +401,8 @@ class MultipleVhostsTest(util.ApacheTest): self.config.save() # Verify ssl_module was enabled. - self.assertIs(self.vh_truth[1].enabled, True) - self.assertIn("ssl_module", self.config.parser.modules) + assert self.vh_truth[1].enabled is True + assert "ssl_module" in self.config.parser.modules loc_cert = self.config.parser.find_dir( "sslcertificatefile", "example/cert.pem", self.vh_truth[1].path) @@ -420,28 +413,25 @@ class MultipleVhostsTest(util.ApacheTest): self.vh_truth[1].path) # Verify one directive was found in the correct file - self.assertEqual(len(loc_cert), 1) - self.assertEqual( - apache_util.get_file_path(loc_cert[0]), - self.vh_truth[1].filep) + assert len(loc_cert) == 1 + assert apache_util.get_file_path(loc_cert[0]) == \ + self.vh_truth[1].filep - self.assertEqual(len(loc_key), 1) - self.assertEqual( - apache_util.get_file_path(loc_key[0]), - self.vh_truth[1].filep) + assert len(loc_key) == 1 + assert apache_util.get_file_path(loc_key[0]) == \ + self.vh_truth[1].filep - self.assertEqual(len(loc_chain), 1) - self.assertEqual( - apache_util.get_file_path(loc_chain[0]), - self.vh_truth[1].filep) + assert len(loc_chain) == 1 + assert apache_util.get_file_path(loc_chain[0]) == \ + self.vh_truth[1].filep # One more time for chain directive setting self.config.deploy_cert( "random.demo", "two/cert.pem", "two/key.pem", "two/cert_chain.pem") - self.assertTrue(self.config.parser.find_dir( + assert self.config.parser.find_dir( "SSLCertificateChainFile", "two/cert_chain.pem", - self.vh_truth[1].path)) + self.vh_truth[1].path) def test_add_listen_80(self): mock_find = mock.Mock() @@ -450,10 +440,10 @@ class MultipleVhostsTest(util.ApacheTest): self.config.parser.find_dir = mock_find self.config.parser.add_dir = mock_add_dir self.config.ensure_listen("80") - self.assertIs(mock_add_dir.called, True) - self.assertIs(mock_find.called, True) - self.assertEqual(mock_add_dir.call_args[0][1], "Listen") - self.assertEqual(mock_add_dir.call_args[0][2], "80") + assert mock_add_dir.called is True + assert mock_find.called is True + assert mock_add_dir.call_args[0][1] == "Listen" + assert mock_add_dir.call_args[0][2] == "80" def test_add_listen_80_named(self): mock_find = mock.Mock() @@ -467,7 +457,7 @@ class MultipleVhostsTest(util.ApacheTest): self.config.parser.add_dir = mock_add_dir self.config.ensure_listen("80") - self.assertEqual(mock_add_dir.call_count, 0) + assert mock_add_dir.call_count == 0 # Reset return lists and inputs mock_add_dir.reset_mock() @@ -475,14 +465,14 @@ class MultipleVhostsTest(util.ApacheTest): # Test self.config.ensure_listen("8080") - self.assertEqual(mock_add_dir.call_count, 3) - self.assertIs(mock_add_dir.called, True) - self.assertEqual(mock_add_dir.call_args[0][1], "Listen") + assert mock_add_dir.call_count == 3 + assert mock_add_dir.called is True + assert mock_add_dir.call_args[0][1] == "Listen" call_found = False for mock_call in mock_add_dir.mock_calls: if mock_call[1][2] == ['1.2.3.4:8080']: call_found = True - self.assertIs(call_found, True) + assert call_found is True @mock.patch("certbot_apache._internal.parser.ApacheParser.reset_modules") def test_prepare_server_https(self, mock_reset): @@ -498,18 +488,18 @@ class MultipleVhostsTest(util.ApacheTest): self.config.parser.add_dir_to_ifmodssl = mock_add_dir self.config.prepare_server_https("443") # Changing the order these modules are enabled breaks the reverter - self.assertEqual(mock_enable.call_args_list[0][0][0], "socache_shmcb") - self.assertEqual(mock_enable.call_args[0][0], "ssl") - self.assertEqual(mock_enable.call_args[1], {"temp": False}) + assert mock_enable.call_args_list[0][0][0] == "socache_shmcb" + assert mock_enable.call_args[0][0] == "ssl" + assert mock_enable.call_args[1] == {"temp": False} self.config.prepare_server_https("8080", temp=True) # Changing the order these modules are enabled breaks the reverter - self.assertEqual(mock_enable.call_args_list[2][0][0], "socache_shmcb") - self.assertEqual(mock_enable.call_args[0][0], "ssl") + assert mock_enable.call_args_list[2][0][0] == "socache_shmcb" + assert mock_enable.call_args[0][0] == "ssl" # Enable mod is temporary - self.assertEqual(mock_enable.call_args[1], {"temp": True}) + assert mock_enable.call_args[1] == {"temp": True} - self.assertEqual(mock_add_dir.call_count, 2) + assert mock_add_dir.call_count == 2 @mock.patch("certbot_apache._internal.parser.ApacheParser.reset_modules") def test_prepare_server_https_named_listen(self, mock_reset): @@ -528,7 +518,7 @@ class MultipleVhostsTest(util.ApacheTest): # Test Listen statements with specific ip listeed self.config.prepare_server_https("443") # Should be 0 as one interface already listens to 443 - self.assertEqual(mock_add_dir.call_count, 0) + assert mock_add_dir.call_count == 0 # Reset return lists and inputs mock_add_dir.reset_mock() @@ -536,13 +526,12 @@ class MultipleVhostsTest(util.ApacheTest): # Test self.config.prepare_server_https("8080", temp=True) - self.assertEqual(mock_add_dir.call_count, 3) + assert mock_add_dir.call_count == 3 call_args_list = [mock_add_dir.call_args_list[i][0][2] for i in range(3)] - self.assertEqual( - sorted(call_args_list), + assert sorted(call_args_list) == \ sorted([["1.2.3.4:8080", "https"], ["[::1]:8080", "https"], - ["1.1.1.1:8080", "https"]])) + ["1.1.1.1:8080", "https"]]) # mock_get.side_effect = ["1.2.3.4:80", "[::1]:80"] # mock_find.return_value = ["test1", "test2", "test3"] @@ -565,7 +554,7 @@ class MultipleVhostsTest(util.ApacheTest): self.config.enable_mod = mock_enable self.config.prepare_server_https("443") - self.assertEqual(mock_add_dir.call_count, 1) + assert mock_add_dir.call_count == 1 @mock.patch("certbot_apache._internal.parser.ApacheParser.reset_modules") def test_prepare_server_https_mixed_listen(self, mock_reset): @@ -585,7 +574,7 @@ class MultipleVhostsTest(util.ApacheTest): self.config.prepare_server_https("443") # Should only be 2 here, as the third interface # already listens to the correct port - self.assertEqual(mock_add_dir.call_count, 0) + assert mock_add_dir.call_count == 0 def test_make_vhost_ssl_with_mock_span(self): # span excludes the closing tag in older versions @@ -605,32 +594,31 @@ class MultipleVhostsTest(util.ApacheTest): def test_make_vhost_ssl_nonsymlink(self): ssl_vhost_slink = self.config.make_vhost_ssl(self.vh_truth[8]) - self.assertIs(ssl_vhost_slink.ssl, True) - self.assertIs(ssl_vhost_slink.enabled, True) - self.assertEqual(ssl_vhost_slink.name, "nonsym.link") + assert ssl_vhost_slink.ssl is True + assert ssl_vhost_slink.enabled is True + assert ssl_vhost_slink.name == "nonsym.link" def test_make_vhost_ssl_nonexistent_vhost_path(self): ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[1]) - self.assertEqual(os.path.dirname(ssl_vhost.filep), - os.path.dirname(filesystem.realpath(self.vh_truth[1].filep))) + assert os.path.dirname(ssl_vhost.filep) == \ + os.path.dirname(filesystem.realpath(self.vh_truth[1].filep)) def test_make_vhost_ssl(self): ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[0]) - self.assertEqual( - ssl_vhost.filep, + assert ssl_vhost.filep == \ os.path.join(self.config_path, "sites-available", - "encryption-example-le-ssl.conf")) + "encryption-example-le-ssl.conf") - self.assertEqual(ssl_vhost.path, - "/files" + ssl_vhost.filep + "/IfModule/Virtualhost") - self.assertEqual(len(ssl_vhost.addrs), 1) - self.assertEqual({obj.Addr.fromstring("*:443")}, ssl_vhost.addrs) - self.assertEqual(ssl_vhost.name, "encryption-example.demo") - self.assertIs(ssl_vhost.ssl, True) - self.assertIs(ssl_vhost.enabled, False) + assert ssl_vhost.path == \ + "/files" + ssl_vhost.filep + "/IfModule/Virtualhost" + assert len(ssl_vhost.addrs) == 1 + assert {obj.Addr.fromstring("*:443")} == ssl_vhost.addrs + assert ssl_vhost.name == "encryption-example.demo" + assert ssl_vhost.ssl is True + assert ssl_vhost.enabled is False - self.assertEqual(len(self.config.vhosts), 13) + assert len(self.config.vhosts) == 13 def test_clean_vhost_ssl(self): # pylint: disable=protected-access @@ -653,12 +641,12 @@ class MultipleVhostsTest(util.ApacheTest): loc_cacert = self.config.parser.find_dir( 'SSLCACertificatePath', None, self.vh_truth[1].path, False) - self.assertEqual(len(loc_cert), 1) - self.assertEqual(len(loc_key), 1) + assert len(loc_cert) == 1 + assert len(loc_key) == 1 - self.assertEqual(len(loc_chain), 0) + assert len(loc_chain) == 0 - self.assertEqual(len(loc_cacert), 10) + assert len(loc_cacert) == 10 def test_deduplicate_directives(self): # pylint: disable=protected-access @@ -671,9 +659,8 @@ class MultipleVhostsTest(util.ApacheTest): self.config._deduplicate_directives(self.vh_truth[1].path, [DIRECTIVE]) self.config.save() - self.assertEqual( - len(self.config.parser.find_dir( - DIRECTIVE, None, self.vh_truth[1].path, False)), 1) + assert len(self.config.parser.find_dir( + DIRECTIVE, None, self.vh_truth[1].path, False)) == 1 def test_remove_directives(self): # pylint: disable=protected-access @@ -688,9 +675,8 @@ class MultipleVhostsTest(util.ApacheTest): self.config.save() for directive in DIRECTIVES: - self.assertEqual( - len(self.config.parser.find_dir( - directive, None, self.vh_truth[2].path, False)), 0) + assert len(self.config.parser.find_dir( + directive, None, self.vh_truth[2].path, False)) == 0 def test_make_vhost_ssl_bad_write(self): mock_open = mock.mock_open() @@ -698,13 +684,12 @@ class MultipleVhostsTest(util.ApacheTest): self.config.reverter.register_file_creation = mock.Mock() mock_open.side_effect = IOError with mock.patch("builtins.open", mock_open): - self.assertRaises( - errors.PluginError, - self.config.make_vhost_ssl, self.vh_truth[0]) + with pytest.raises(errors.PluginError): + self.config.make_vhost_ssl(self.vh_truth[0]) def test_get_ssl_vhost_path(self): # pylint: disable=protected-access - self.assertIs(self.config._get_ssl_vhost_path("example_path").endswith(".conf"), True) + assert self.config._get_ssl_vhost_path("example_path").endswith(".conf") is True @mock.patch("certbot_apache._internal.configurator.http_01.ApacheHttp01.perform") @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart") @@ -718,10 +703,10 @@ class MultipleVhostsTest(util.ApacheTest): responses = self.config.perform(achalls) - self.assertEqual(mock_http_perform.call_count, 1) - self.assertEqual(responses, expected) + assert mock_http_perform.call_count == 1 + assert responses == expected - self.assertEqual(mock_restart.call_count, 1) + assert mock_restart.call_count == 1 @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart") @mock.patch("certbot_apache._internal.apache_util._get_runtime_cfg") @@ -735,9 +720,9 @@ class MultipleVhostsTest(util.ApacheTest): for i, achall in enumerate(achalls): self.config.cleanup([achall]) if i == len(achalls) - 1: - self.assertIs(mock_restart.called, True) + assert mock_restart.called is True else: - self.assertIs(mock_restart.called, False) + assert mock_restart.called is False @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart") @mock.patch("certbot_apache._internal.apache_util._get_runtime_cfg") @@ -750,32 +735,35 @@ class MultipleVhostsTest(util.ApacheTest): self.config._chall_out.add(achall) # pylint: disable=protected-access self.config.cleanup([achalls[-1]]) - self.assertIs(mock_restart.called, False) + assert mock_restart.called is False self.config.cleanup(achalls) - self.assertIs(mock_restart.called, True) + assert mock_restart.called is True @mock.patch("certbot.util.run_script") def test_get_version(self, mock_script): mock_script.return_value = ( "Server Version: Apache/2.4.2 (Debian)", "") - self.assertEqual(self.config.get_version(), (2, 4, 2)) + assert self.config.get_version() == (2, 4, 2) mock_script.return_value = ( "Server Version: Apache/2 (Linux)", "") - self.assertEqual(self.config.get_version(), (2,)) + assert self.config.get_version() == (2,) mock_script.return_value = ( "Server Version: Apache (Debian)", "") - self.assertRaises(errors.PluginError, self.config.get_version) + with pytest.raises(errors.PluginError): + self.config.get_version() mock_script.return_value = ( "Server Version: Apache/2.3{0} Apache/2.4.7".format( os.linesep), "") - self.assertRaises(errors.PluginError, self.config.get_version) + with pytest.raises(errors.PluginError): + self.config.get_version() mock_script.side_effect = errors.SubprocessError("Can't find program") - self.assertRaises(errors.PluginError, self.config.get_version) + with pytest.raises(errors.PluginError): + self.config.get_version() @mock.patch("certbot_apache._internal.configurator.util.run_script") def test_restart(self, _): @@ -785,7 +773,8 @@ class MultipleVhostsTest(util.ApacheTest): def test_restart_bad_process(self, mock_run_script): mock_run_script.side_effect = [None, errors.SubprocessError] - self.assertRaises(errors.MisconfigurationError, self.config.restart) + with pytest.raises(errors.MisconfigurationError): + self.config.restart() @mock.patch("certbot.util.run_script") def test_config_test(self, _): @@ -795,25 +784,25 @@ class MultipleVhostsTest(util.ApacheTest): def test_config_test_bad_process(self, mock_run_script): mock_run_script.side_effect = errors.SubprocessError - self.assertRaises(errors.MisconfigurationError, - self.config.config_test) + with pytest.raises(errors.MisconfigurationError): + self.config.config_test() def test_more_info(self): - self.assertTrue(self.config.more_info()) + assert self.config.more_info() def test_get_chall_pref(self): - self.assertIsInstance(self.config.get_chall_pref(""), list) + assert isinstance(self.config.get_chall_pref(""), list) def test_install_ssl_options_conf(self): path = os.path.join(self.work_dir, "test_it") other_path = os.path.join(self.work_dir, "other_test_it") self.config.install_ssl_options_conf(path, other_path) - self.assertIs(os.path.isfile(path), True) - self.assertIs(os.path.isfile(other_path), True) + assert os.path.isfile(path) is True + assert os.path.isfile(other_path) is True # TEST ENHANCEMENTS def test_supported_enhancements(self): - self.assertIsInstance(self.config.supported_enhancements(), list) + assert isinstance(self.config.supported_enhancements(), list) def test_find_http_vhost_without_ancestor(self): # pylint: disable=protected-access @@ -821,8 +810,8 @@ class MultipleVhostsTest(util.ApacheTest): vhost.ssl = True vhost.ancestor = None res = self.config._get_http_vhost(vhost) - self.assertEqual(self.vh_truth[0].name, res.name) - self.assertEqual(self.vh_truth[0].aliases, res.aliases) + assert self.vh_truth[0].name == res.name + assert self.vh_truth[0].aliases == res.aliases @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._get_http_vhost") @mock.patch("certbot_apache._internal.display_ops.select_vhost") @@ -838,30 +827,28 @@ class MultipleVhostsTest(util.ApacheTest): mock_sel_vhost.return_value = None mock_get.return_value = None - self.assertRaises( - errors.PluginError, - self.config.enhance, "satoshi.com", "redirect") + with pytest.raises(errors.PluginError): + self.config.enhance("satoshi.com", "redirect") def test_enhance_unknown_enhancement(self): - self.assertRaises( - errors.PluginError, - self.config.enhance, "certbot.demo", "unknown_enhancement") + with pytest.raises(errors.PluginError): + self.config.enhance("certbot.demo", "unknown_enhancement") def test_enhance_no_ssl_vhost(self): with mock.patch("certbot_apache._internal.configurator.logger.error") as mock_log: - self.assertRaises(errors.PluginError, self.config.enhance, - "certbot.demo", "redirect") + with pytest.raises(errors.PluginError): + self.config.enhance("certbot.demo", "redirect") # Check that correct logger.warning was printed - self.assertIn("not able to find", mock_log.call_args[0][0]) - self.assertIn("\"redirect\"", mock_log.call_args[0][0]) + assert "not able to find" in mock_log.call_args[0][0] + assert "\"redirect\"" in mock_log.call_args[0][0] mock_log.reset_mock() - self.assertRaises(errors.PluginError, self.config.enhance, - "certbot.demo", "ensure-http-header", "Test") + with pytest.raises(errors.PluginError): + self.config.enhance("certbot.demo", "ensure-http-header", "Test") # Check that correct logger.warning was printed - self.assertIn("not able to find", mock_log.call_args[0][0]) - self.assertIn("Test", mock_log.call_args[0][0]) + assert "not able to find" in mock_log.call_args[0][0] + assert "Test" in mock_log.call_args[0][0] @mock.patch("certbot.util.exe_exists") def test_ocsp_stapling(self, mock_exe): @@ -881,14 +868,14 @@ class MultipleVhostsTest(util.ApacheTest): ssl_use_stapling_aug_path = self.config.parser.find_dir( "SSLUseStapling", "on", ssl_vhost.path) - self.assertEqual(len(ssl_use_stapling_aug_path), 1) + assert len(ssl_use_stapling_aug_path) == 1 ssl_vhost_aug_path = parser.get_aug_path(ssl_vhost.filep) stapling_cache_aug_path = self.config.parser.find_dir('SSLStaplingCache', "shmcb:/var/run/apache2/stapling_cache(128000)", ssl_vhost_aug_path) - self.assertEqual(len(stapling_cache_aug_path), 1) + assert len(stapling_cache_aug_path) == 1 @mock.patch("certbot.util.exe_exists") def test_ocsp_stapling_twice(self, mock_exe): @@ -908,13 +895,13 @@ class MultipleVhostsTest(util.ApacheTest): ssl_use_stapling_aug_path = self.config.parser.find_dir( "SSLUseStapling", "on", ssl_vhost.path) - self.assertEqual(len(ssl_use_stapling_aug_path), 1) + assert len(ssl_use_stapling_aug_path) == 1 ssl_vhost_aug_path = parser.get_aug_path(ssl_vhost.filep) stapling_cache_aug_path = self.config.parser.find_dir('SSLStaplingCache', "shmcb:/var/run/apache2/stapling_cache(128000)", ssl_vhost_aug_path) - self.assertEqual(len(stapling_cache_aug_path), 1) + assert len(stapling_cache_aug_path) == 1 def test_get_http_vhost_third_filter(self): ssl_vh = obj.VirtualHost( @@ -925,7 +912,7 @@ class MultipleVhostsTest(util.ApacheTest): # pylint: disable=protected-access http_vh = self.config._get_http_vhost(ssl_vh) - self.assertIs(http_vh.ssl, False) + assert http_vh.ssl is False @mock.patch("certbot.util.run_script") @mock.patch("certbot.util.exe_exists") @@ -949,7 +936,7 @@ class MultipleVhostsTest(util.ApacheTest): "Header", None, ssl_vhost.path) # four args to HSTS header - self.assertEqual(len(hsts_header), 4) + assert len(hsts_header) == 4 def test_http_header_hsts_twice(self): self.config.parser.modules["mod_ssl.c"] = None @@ -961,9 +948,8 @@ class MultipleVhostsTest(util.ApacheTest): self.config.enhance("encryption-example.demo", "ensure-http-header", "Strict-Transport-Security") - self.assertRaises( - errors.PluginEnhancementAlreadyPresent, - self.config.enhance, "encryption-example.demo", + with pytest.raises(errors.PluginEnhancementAlreadyPresent): + self.config.enhance("encryption-example.demo", "ensure-http-header", "Strict-Transport-Security") @mock.patch("certbot.util.run_script") @@ -980,7 +966,7 @@ class MultipleVhostsTest(util.ApacheTest): self.config.enhance("certbot.demo", "ensure-http-header", "Upgrade-Insecure-Requests") - self.assertIn("headers_module", self.config.parser.modules) + assert "headers_module" in self.config.parser.modules # Get the ssl vhost for certbot.demo ssl_vhost = self.config.assoc["certbot.demo"] @@ -991,7 +977,7 @@ class MultipleVhostsTest(util.ApacheTest): "Header", None, ssl_vhost.path) # four args to HSTS header - self.assertEqual(len(uir_header), 4) + assert len(uir_header) == 4 def test_http_header_uir_twice(self): self.config.parser.modules["mod_ssl.c"] = None @@ -1003,9 +989,8 @@ class MultipleVhostsTest(util.ApacheTest): self.config.enhance("encryption-example.demo", "ensure-http-header", "Upgrade-Insecure-Requests") - self.assertRaises( - errors.PluginEnhancementAlreadyPresent, - self.config.enhance, "encryption-example.demo", + with pytest.raises(errors.PluginEnhancementAlreadyPresent): + self.config.enhance("encryption-example.demo", "ensure-http-header", "Upgrade-Insecure-Requests") @mock.patch("certbot.util.run_script") @@ -1027,13 +1012,13 @@ class MultipleVhostsTest(util.ApacheTest): rw_rule = self.config.parser.find_dir( "RewriteRule", None, self.vh_truth[3].path) - self.assertEqual(len(rw_engine), 1) + assert len(rw_engine) == 1 # three args to rw_rule - self.assertEqual(len(rw_rule), 3) + assert len(rw_rule) == 3 # [:-3] to remove the vhost index number - self.assertIs(rw_engine[0].startswith(self.vh_truth[3].path[:-3]), True) - self.assertIs(rw_rule[0].startswith(self.vh_truth[3].path[:-3]), True) + assert rw_engine[0].startswith(self.vh_truth[3].path[:-3]) is True + assert rw_rule[0].startswith(self.vh_truth[3].path[:-3]) is True def test_rewrite_rule_exists(self): # Skip the enable mod @@ -1042,7 +1027,7 @@ class MultipleVhostsTest(util.ApacheTest): self.config.parser.add_dir( self.vh_truth[3].path, "RewriteRule", ["Unknown"]) # pylint: disable=protected-access - self.assertIs(self.config._is_rewrite_exists(self.vh_truth[3]), True) + assert self.config._is_rewrite_exists(self.vh_truth[3]) is True def test_rewrite_engine_exists(self): # Skip the enable mod @@ -1051,7 +1036,7 @@ class MultipleVhostsTest(util.ApacheTest): self.config.parser.add_dir( self.vh_truth[3].path, "RewriteEngine", "on") # pylint: disable=protected-access - self.assertTrue(self.config._is_rewrite_engine_on(self.vh_truth[3])) + assert self.config._is_rewrite_engine_on(self.vh_truth[3]) @mock.patch("certbot.util.run_script") @mock.patch("certbot.util.exe_exists") @@ -1078,14 +1063,14 @@ class MultipleVhostsTest(util.ApacheTest): rw_rule = self.config.parser.find_dir( "RewriteRule", None, self.vh_truth[3].path) - self.assertEqual(len(rw_engine), 1) + assert len(rw_engine) == 1 # three args to rw_rule + 1 arg for the pre existing rewrite - self.assertEqual(len(rw_rule), 5) + assert len(rw_rule) == 5 # [:-3] to remove the vhost index number - self.assertIs(rw_engine[0].startswith(self.vh_truth[3].path[:-3]), True) - self.assertIs(rw_rule[0].startswith(self.vh_truth[3].path[:-3]), True) + assert rw_engine[0].startswith(self.vh_truth[3].path[:-3]) is True + assert rw_rule[0].startswith(self.vh_truth[3].path[:-3]) is True - self.assertIn("rewrite_module", self.config.parser.modules) + assert "rewrite_module" in self.config.parser.modules @mock.patch("certbot.util.run_script") @mock.patch("certbot.util.exe_exists") @@ -1115,7 +1100,7 @@ class MultipleVhostsTest(util.ApacheTest): args_paths = self.config.parser.find_dir( "RewriteRule", None, http_vhost.path, False) arg_vals = [self.config.parser.aug.get(x) for x in args_paths] - self.assertEqual(arg_vals, constants.REWRITE_HTTPS_ARGS) + assert arg_vals == constants.REWRITE_HTTPS_ARGS def test_redirect_with_conflict(self): @@ -1127,8 +1112,8 @@ class MultipleVhostsTest(util.ApacheTest): # No names ^ this guy should conflict. # pylint: disable=protected-access - self.assertRaises( - errors.PluginError, self.config._enable_redirect, ssl_vh, "") + with pytest.raises(errors.PluginError): + self.config._enable_redirect(ssl_vh, "") def test_redirect_two_domains_one_vhost(self): # Skip the enable mod @@ -1143,7 +1128,7 @@ class MultipleVhostsTest(util.ApacheTest): "ApacheConfigurator._verify_no_certbot_redirect") with mock.patch(verify_no_redirect) as mock_verify: self.config.enhance("green.blue.purple.com", "redirect") - self.assertIs(mock_verify.called, False) + assert mock_verify.called is False def test_redirect_from_previous_run(self): # Skip the enable mod @@ -1155,9 +1140,8 @@ class MultipleVhostsTest(util.ApacheTest): # pylint: disable=protected-access self.config._enhanced_vhosts["redirect"].clear() - self.assertRaises( - errors.PluginEnhancementAlreadyPresent, - self.config.enhance, "green.blue.purple.com", "redirect") + with pytest.raises(errors.PluginEnhancementAlreadyPresent): + self.config.enhance("green.blue.purple.com", "redirect") def test_create_own_redirect(self): self.config.parser.modules["rewrite_module"] = None @@ -1168,7 +1152,7 @@ class MultipleVhostsTest(util.ApacheTest): # pylint: disable=protected-access self.config._enable_redirect(self.vh_truth[1], "") - self.assertEqual(len(self.config.vhosts), 13) + assert len(self.config.vhosts) == 13 def test_create_own_redirect_for_old_apache_version(self): self.config.parser.modules["rewrite_module"] = None @@ -1179,21 +1163,21 @@ class MultipleVhostsTest(util.ApacheTest): # pylint: disable=protected-access self.config._enable_redirect(self.vh_truth[1], "") - self.assertEqual(len(self.config.vhosts), 13) + assert len(self.config.vhosts) == 13 def test_sift_rewrite_rule(self): # pylint: disable=protected-access small_quoted_target = "RewriteRule ^ \"http://\"" - self.assertIs(self.config._sift_rewrite_rule(small_quoted_target), False) + assert self.config._sift_rewrite_rule(small_quoted_target) is False https_target = "RewriteRule ^ https://satoshi" - self.assertIs(self.config._sift_rewrite_rule(https_target), True) + assert self.config._sift_rewrite_rule(https_target) is True normal_target = "RewriteRule ^/(.*) http://www.a.com:1234/$1 [L,R]" - self.assertIs(self.config._sift_rewrite_rule(normal_target), False) + assert self.config._sift_rewrite_rule(normal_target) is False not_rewriterule = "NotRewriteRule ^ ..." - self.assertIs(self.config._sift_rewrite_rule(not_rewriterule), False) + assert self.config._sift_rewrite_rule(not_rewriterule) is False def get_key_and_achalls(self): """Return testing achallenges.""" @@ -1222,14 +1206,13 @@ class MultipleVhostsTest(util.ApacheTest): vhost = self.vh_truth[0] vhost.enabled = False vhost.filep = inc_path - self.assertEqual(self.config.parser.find_dir("Include", inc_path), []) - self.assertNotIn(os.path.dirname(inc_path), self.config.parser.existing_paths) + assert self.config.parser.find_dir("Include", inc_path) == [] + assert os.path.dirname(inc_path) not in self.config.parser.existing_paths self.config.enable_site(vhost) - self.assertGreaterEqual(len(self.config.parser.find_dir("Include", inc_path)), 1) - self.assertIn(os.path.dirname(inc_path), self.config.parser.existing_paths) - self.assertIn( - os.path.basename(inc_path), self.config.parser.existing_paths[ - os.path.dirname(inc_path)]) + assert len(self.config.parser.find_dir("Include", inc_path)) >= 1 + assert os.path.dirname(inc_path) in self.config.parser.existing_paths + assert os.path.basename(inc_path) in self.config.parser.existing_paths[ + os.path.dirname(inc_path)] @mock.patch('certbot_apache._internal.configurator.display_util.notify') def test_deploy_cert_not_parsed_path(self, unused_mock_notify): @@ -1251,7 +1234,7 @@ class MultipleVhostsTest(util.ApacheTest): "example/cert.pem", "example/key.pem", "example/cert_chain.pem") # Test that we actually called add_include - self.assertIs(mock_add.called, True) + assert mock_add.called is True shutil.rmtree(tmp_path) def test_deploy_cert_no_mod_ssl(self): @@ -1260,8 +1243,8 @@ class MultipleVhostsTest(util.ApacheTest): self.config.parser.modules["socache_shmcb_module"] = None self.config.prepare_server_https = mock.Mock() - self.assertRaises(errors.MisconfigurationError, self.config.deploy_cert, - "encryption-example.demo", "example/cert.pem", "example/key.pem", + with pytest.raises(errors.MisconfigurationError): + self.config.deploy_cert("encryption-example.demo", "example/cert.pem", "example/key.pem", "example/cert_chain.pem", "example/fullchain.pem") @mock.patch("certbot_apache._internal.parser.ApacheParser.parsed_in_original") @@ -1270,12 +1253,11 @@ class MultipleVhostsTest(util.ApacheTest): ret_vh.enabled = True self.config.enable_site(ret_vh) # Make sure that we return early - self.assertIs(mock_parsed.called, False) + assert mock_parsed.called is False def test_enable_mod_unsupported(self): - self.assertRaises(errors.MisconfigurationError, - self.config.enable_mod, - "whatever") + with pytest.raises(errors.MisconfigurationError): + self.config.enable_mod("whatever") def test_choose_vhosts_wildcard(self): # pylint: disable=protected-access @@ -1285,15 +1267,15 @@ class MultipleVhostsTest(util.ApacheTest): vhs = self.config._choose_vhosts_wildcard("*.certbot.demo", create_ssl=True) # Check that the dialog was called with one vh: certbot.demo - self.assertEqual(mock_select_vhs.call_args[0][0][0], self.vh_truth[3]) - self.assertEqual(len(mock_select_vhs.call_args_list), 1) + assert mock_select_vhs.call_args[0][0][0] == self.vh_truth[3] + assert len(mock_select_vhs.call_args_list) == 1 # And the actual returned values - self.assertEqual(len(vhs), 1) - self.assertEqual(vhs[0].name, "certbot.demo") - self.assertIs(vhs[0].ssl, True) + assert len(vhs) == 1 + assert vhs[0].name == "certbot.demo" + assert vhs[0].ssl is True - self.assertNotEqual(vhs[0], self.vh_truth[3]) + assert vhs[0] != self.vh_truth[3] @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.make_vhost_ssl") def test_choose_vhosts_wildcard_no_ssl(self, mock_makessl): @@ -1303,8 +1285,8 @@ class MultipleVhostsTest(util.ApacheTest): mock_select_vhs.return_value = [self.vh_truth[1]] vhs = self.config._choose_vhosts_wildcard("*.certbot.demo", create_ssl=False) - self.assertIs(mock_makessl.called, False) - self.assertEqual(vhs[0], self.vh_truth[1]) + assert mock_makessl.called is False + assert vhs[0] == self.vh_truth[1] @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._vhosts_for_wildcard") @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.make_vhost_ssl") @@ -1317,15 +1299,15 @@ class MultipleVhostsTest(util.ApacheTest): mock_select_vhs.return_value = [self.vh_truth[7]] vhs = self.config._choose_vhosts_wildcard("whatever", create_ssl=True) - self.assertEqual(mock_select_vhs.call_args[0][0][0], self.vh_truth[7]) - self.assertEqual(len(mock_select_vhs.call_args_list), 1) + assert mock_select_vhs.call_args[0][0][0] == self.vh_truth[7] + assert len(mock_select_vhs.call_args_list) == 1 # Ensure that make_vhost_ssl was not called, vhost.ssl == true - self.assertIs(mock_makessl.called, False) + assert mock_makessl.called is False # And the actual returned values - self.assertEqual(len(vhs), 1) - self.assertIs(vhs[0].ssl, True) - self.assertEqual(vhs[0], self.vh_truth[7]) + assert len(vhs) == 1 + assert vhs[0].ssl is True + assert vhs[0] == self.vh_truth[7] @mock.patch('certbot_apache._internal.configurator.display_util.notify') def test_deploy_cert_wildcard(self, unused_mock_notify): @@ -1337,17 +1319,16 @@ class MultipleVhostsTest(util.ApacheTest): with mock.patch(mock_d) as mock_dep: self.config.deploy_cert("*.wildcard.example.org", "/tmp/path", "/tmp/path", "/tmp/path", "/tmp/path") - self.assertIs(mock_dep.called, True) - self.assertEqual(len(mock_dep.call_args_list), 1) - self.assertEqual(self.vh_truth[7], mock_dep.call_args_list[0][0][0]) + assert mock_dep.called is True + assert len(mock_dep.call_args_list) == 1 + assert self.vh_truth[7] == mock_dep.call_args_list[0][0][0] @mock.patch("certbot_apache._internal.display_ops.select_vhost_multiple") def test_deploy_cert_wildcard_no_vhosts(self, mock_dialog): # pylint: disable=protected-access mock_dialog.return_value = [] - self.assertRaises(errors.PluginError, - self.config.deploy_cert, - "*.wild.cat", "/tmp/path", "/tmp/path", + with pytest.raises(errors.PluginError): + self.config.deploy_cert("*.wild.cat", "/tmp/path", "/tmp/path", "/tmp/path", "/tmp/path") @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._choose_vhosts_wildcard") @@ -1359,7 +1340,7 @@ class MultipleVhostsTest(util.ApacheTest): self.config._wildcard_vhosts["*.certbot.demo"] = [self.vh_truth[3]] self.config.enhance("*.certbot.demo", "ensure-http-header", "Upgrade-Insecure-Requests") - self.assertIs(mock_choose.called, False) + assert mock_choose.called is False @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._choose_vhosts_wildcard") def test_enhance_wildcard_no_install(self, mock_choose): @@ -1369,22 +1350,21 @@ class MultipleVhostsTest(util.ApacheTest): self.config.parser.modules["headers_module"] = None self.config.enhance("*.certbot.demo", "ensure-http-header", "Upgrade-Insecure-Requests") - self.assertIs(mock_choose.called, True) + assert mock_choose.called is True def test_add_vhost_id(self): for vh in [self.vh_truth[0], self.vh_truth[1], self.vh_truth[2]]: vh_id = self.config.add_vhost_id(vh) - self.assertEqual(vh, self.config.find_vhost_by_id(vh_id)) + assert vh == self.config.find_vhost_by_id(vh_id) def test_find_vhost_by_id_404(self): - self.assertRaises(errors.PluginError, - self.config.find_vhost_by_id, - "nonexistent") + with pytest.raises(errors.PluginError): + self.config.find_vhost_by_id("nonexistent") def test_add_vhost_id_already_exists(self): first_id = self.config.add_vhost_id(self.vh_truth[0]) second_id = self.config.add_vhost_id(self.vh_truth[0]) - self.assertEqual(first_id, second_id) + assert first_id == second_id def test_realpath_replaces_symlink(self): orig_match = self.config.parser.aug.match @@ -1403,11 +1383,11 @@ class MultipleVhostsTest(util.ApacheTest): self.config.parser.parser_paths = ["/mocked/path"] self.config.parser.aug.match = mock_match vhs = self.config.get_virtual_hosts() - self.assertEqual(len(vhs), 2) - self.assertEqual(vhs[0], self.vh_truth[1]) + assert len(vhs) == 2 + assert vhs[0] == self.vh_truth[1] # mock_vhost should have replaced the vh_truth[0], because its filepath # isn't a symlink - self.assertEqual(vhs[1], mock_vhost) + assert vhs[1] == mock_vhost class AugeasVhostsTest(util.ApacheTest): @@ -1431,25 +1411,25 @@ class AugeasVhostsTest(util.ApacheTest): self.config.parser.aug.match.side_effect = RuntimeError path = "debian_apache_2_4/augeas_vhosts/apache2/sites-available/old-and-default.conf" chosen_vhost = self.config._create_vhost(path) - self.assertEqual(None, chosen_vhost) + assert None == chosen_vhost def test_choosevhost_works(self): path = "debian_apache_2_4/augeas_vhosts/apache2/sites-available/old-and-default.conf" chosen_vhost = self.config._create_vhost(path) - self.assertTrue(chosen_vhost is None or chosen_vhost.path == path) + assert chosen_vhost is None or chosen_vhost.path == path @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._create_vhost") def test_get_vhost_continue(self, mock_vhost): mock_vhost.return_value = None vhs = self.config.get_virtual_hosts() - self.assertEqual([], vhs) + assert [] == vhs def test_choose_vhost_with_matching_wildcard(self): names = ( "an.example.net", "another.example.net", "an.other.example.net") for name in names: with self.subTest(name=name): - self.assertNotIn(name, self.config.choose_vhost(name).aliases) + assert name not in self.config.choose_vhost(name).aliases @mock.patch("certbot_apache._internal.obj.VirtualHost.conflicts") def test_choose_vhost_without_matching_wildcard(self, mock_conflicts): @@ -1457,7 +1437,7 @@ class AugeasVhostsTest(util.ApacheTest): mock_path = "certbot_apache._internal.display_ops.select_vhost" with mock.patch(mock_path, lambda _, vhosts: vhosts[0]): for name in ("a.example.net", "other.example.net"): - self.assertIn(name, self.config.choose_vhost(name).aliases) + assert name in self.config.choose_vhost(name).aliases @mock.patch("certbot_apache._internal.obj.VirtualHost.conflicts") def test_choose_vhost_wildcard_not_found(self, mock_conflicts): @@ -1471,7 +1451,7 @@ class AugeasVhostsTest(util.ApacheTest): for name in names: orig_cc = mock_select.call_count self.config.choose_vhost(name) - self.assertEqual(mock_select.call_count - orig_cc, 1) + assert mock_select.call_count - orig_cc == 1 def test_choose_vhost_wildcard_found(self): mock_path = "certbot_apache._internal.display_ops.select_vhost" @@ -1482,13 +1462,13 @@ class AugeasVhostsTest(util.ApacheTest): mock_select.return_value = self.config.vhosts[0] for name in names: self.config.choose_vhost(name) - self.assertEqual(mock_select.call_count, 0) + assert mock_select.call_count == 0 def test_augeas_span_error(self): broken_vhost = self.config.vhosts[0] broken_vhost.path = broken_vhost.path + "/nonexistent" - self.assertRaises(errors.PluginError, self.config.make_vhost_ssl, - broken_vhost) + with pytest.raises(errors.PluginError): + self.config.make_vhost_ssl(broken_vhost) class MultiVhostsTest(util.ApacheTest): @@ -1510,39 +1490,38 @@ class MultiVhostsTest(util.ApacheTest): def test_make_vhost_ssl(self): ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[1]) - self.assertEqual( - ssl_vhost.filep, + assert ssl_vhost.filep == \ os.path.join(self.config_path, "sites-available", - "default-le-ssl.conf")) + "default-le-ssl.conf") - self.assertEqual(ssl_vhost.path, - "/files" + ssl_vhost.filep + "/IfModule/VirtualHost") - self.assertEqual(len(ssl_vhost.addrs), 1) - self.assertEqual({obj.Addr.fromstring("*:443")}, ssl_vhost.addrs) - self.assertEqual(ssl_vhost.name, "banana.vomit.com") - self.assertIs(ssl_vhost.ssl, True) - self.assertIs(ssl_vhost.enabled, False) + assert ssl_vhost.path == \ + "/files" + ssl_vhost.filep + "/IfModule/VirtualHost" + assert len(ssl_vhost.addrs) == 1 + assert {obj.Addr.fromstring("*:443")} == ssl_vhost.addrs + assert ssl_vhost.name == "banana.vomit.com" + assert ssl_vhost.ssl is True + assert ssl_vhost.enabled is False mock_path = "certbot_apache._internal.configurator.ApacheConfigurator._get_new_vh_path" with mock.patch(mock_path) as mock_getpath: mock_getpath.return_value = None - self.assertRaises(errors.PluginError, self.config.make_vhost_ssl, - self.vh_truth[1]) + with pytest.raises(errors.PluginError): + self.config.make_vhost_ssl(self.vh_truth[1]) def test_get_new_path(self): with_index_1 = ["/path[1]/section[1]"] without_index = ["/path/section"] with_index_2 = ["/path[2]/section[2]"] - self.assertEqual(self.config._get_new_vh_path(without_index, - with_index_1), - None) - self.assertEqual(self.config._get_new_vh_path(without_index, - with_index_2), - with_index_2[0]) + assert self.config._get_new_vh_path(without_index, + with_index_1) == \ + None + assert self.config._get_new_vh_path(without_index, + with_index_2) == \ + with_index_2[0] both = with_index_1 + with_index_2 - self.assertEqual(self.config._get_new_vh_path(without_index, both), - with_index_2[0]) + assert self.config._get_new_vh_path(without_index, both) == \ + with_index_2[0] @mock.patch("certbot_apache._internal.configurator.display_util.notify") def test_make_vhost_ssl_with_existing_rewrite_rule(self, mock_notify): @@ -1550,7 +1529,7 @@ class MultiVhostsTest(util.ApacheTest): ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[4]) - self.assertTrue(self.config.parser.find_dir("RewriteEngine", "on", ssl_vhost.path, False)) + assert self.config.parser.find_dir("RewriteEngine", "on", ssl_vhost.path, False) with open(ssl_vhost.filep) as the_file: conf_text = the_file.read() @@ -1558,10 +1537,10 @@ class MultiVhostsTest(util.ApacheTest): "\"https://new.example.com/docs/$1\" [R,L]") uncommented_rewrite_rule = ("RewriteRule \"^/docs/(.+)\" " "\"http://new.example.com/docs/$1\" [R,L]") - self.assertIn(commented_rewrite_rule, conf_text) - self.assertIn(uncommented_rewrite_rule, conf_text) - self.assertEqual(mock_notify.call_count, 1) - self.assertIn("Some rewrite rules", mock_notify.call_args[0][0]) + assert commented_rewrite_rule in conf_text + assert uncommented_rewrite_rule in conf_text + assert mock_notify.call_count == 1 + assert "Some rewrite rules" in mock_notify.call_args[0][0] @mock.patch("certbot_apache._internal.configurator.display_util.notify") def test_make_vhost_ssl_with_existing_rewrite_conds(self, mock_notify): @@ -1583,14 +1562,14 @@ class MultiVhostsTest(util.ApacheTest): "https://%{SERVER_NAME}%{REQUEST_URI} " "[L,NE,R=permanent]") - self.assertIn(not_commented_cond1, conf_line_set) - self.assertIn(not_commented_rewrite_rule, conf_line_set) + assert not_commented_cond1 in conf_line_set + assert not_commented_rewrite_rule in conf_line_set - self.assertIn(commented_cond1, conf_line_set) - self.assertIn(commented_cond2, conf_line_set) - self.assertIn(commented_rewrite_rule, conf_line_set) - self.assertEqual(mock_notify.call_count, 1) - self.assertIn("Some rewrite rules", mock_notify.call_args[0][0]) + assert commented_cond1 in conf_line_set + assert commented_cond2 in conf_line_set + assert commented_rewrite_rule in conf_line_set + assert mock_notify.call_count == 1 + assert "Some rewrite rules" in mock_notify.call_args[0][0] class InstallSslOptionsConfTest(util.ApacheTest): @@ -1610,15 +1589,15 @@ class InstallSslOptionsConfTest(util.ApacheTest): return crypto_util.sha256sum(self.config.pick_apache_config()) def _assert_current_file(self): - self.assertIs(os.path.isfile(self.config.mod_ssl_conf), True) - self.assertEqual(crypto_util.sha256sum(self.config.mod_ssl_conf), - self._current_ssl_options_hash()) + assert os.path.isfile(self.config.mod_ssl_conf) is True + assert crypto_util.sha256sum(self.config.mod_ssl_conf) == \ + self._current_ssl_options_hash() def test_no_file(self): # prepare should have placed a file there self._assert_current_file() os.remove(self.config.mod_ssl_conf) - self.assertIs(os.path.isfile(self.config.mod_ssl_conf), False) + assert os.path.isfile(self.config.mod_ssl_conf) is False self._call() self._assert_current_file() @@ -1640,13 +1619,13 @@ class InstallSslOptionsConfTest(util.ApacheTest): mod_ssl_conf.write("a new line for the wrong hash\n") with mock.patch("certbot.plugins.common.logger") as mock_logger: self._call() - self.assertIs(mock_logger.warning.called, False) - self.assertIs(os.path.isfile(self.config.mod_ssl_conf), True) - self.assertEqual(crypto_util.sha256sum( - self.config.pick_apache_config()), - self._current_ssl_options_hash()) - self.assertNotEqual(crypto_util.sha256sum(self.config.mod_ssl_conf), - self._current_ssl_options_hash()) + assert mock_logger.warning.called is False + assert os.path.isfile(self.config.mod_ssl_conf) is True + assert crypto_util.sha256sum( + self.config.pick_apache_config()) == \ + self._current_ssl_options_hash() + assert crypto_util.sha256sum(self.config.mod_ssl_conf) != \ + self._current_ssl_options_hash() def test_manually_modified_past_file_warns(self): with open(self.config.mod_ssl_conf, "a") as mod_ssl_conf: @@ -1655,16 +1634,16 @@ class InstallSslOptionsConfTest(util.ApacheTest): f.write("hashofanoldversion") with mock.patch("certbot.plugins.common.logger") as mock_logger: self._call() - self.assertEqual(mock_logger.warning.call_args[0][0], - "%s has been manually modified; updated file " - "saved to %s. We recommend updating %s for security purposes.") - self.assertEqual(crypto_util.sha256sum( - self.config.pick_apache_config()), - self._current_ssl_options_hash()) + assert mock_logger.warning.call_args[0][0] == \ + "%s has been manually modified; updated file " \ + "saved to %s. We recommend updating %s for security purposes." + assert crypto_util.sha256sum( + self.config.pick_apache_config()) == \ + self._current_ssl_options_hash() # only print warning once with mock.patch("certbot.plugins.common.logger") as mock_logger: self._call() - self.assertIs(mock_logger.warning.called, False) + assert mock_logger.warning.called is False def test_ssl_config_files_hash_in_all_hashes(self): """ @@ -1681,14 +1660,12 @@ class InstallSslOptionsConfTest(util.ApacheTest): "certbot_apache", os.path.join("_internal", "tls_configs")) all_files = [os.path.join(tls_configs_dir, name) for name in os.listdir(tls_configs_dir) if name.endswith('options-ssl-apache.conf')] - self.assertGreaterEqual(len(all_files), 1) + assert len(all_files) >= 1 for one_file in all_files: file_hash = crypto_util.sha256sum(one_file) - self.assertIn( - file_hash, ALL_SSL_OPTIONS_HASHES, - f"Constants.ALL_SSL_OPTIONS_HASHES must be appended with the sha256 " + assert file_hash in ALL_SSL_OPTIONS_HASHES, \ + f"Constants.ALL_SSL_OPTIONS_HASHES must be appended with the sha256 " \ f"hash of {one_file} when it is updated." - ) def test_openssl_version(self): self.config._openssl_version = None @@ -1708,7 +1685,7 @@ class InstallSslOptionsConfTest(util.ApacheTest): with mock.patch("certbot_apache._internal.configurator." "ApacheConfigurator._open_module_file") as mock_omf: mock_omf.return_value = some_string_contents - self.assertEqual(self.config.openssl_version(), "1.0.2g") + assert self.config.openssl_version() == "1.0.2g" # ssl_module statically linked self.config._openssl_version = None @@ -1717,49 +1694,49 @@ class InstallSslOptionsConfTest(util.ApacheTest): with mock.patch("certbot_apache._internal.configurator." "ApacheConfigurator._open_module_file") as mock_omf: mock_omf.return_value = some_string_contents - self.assertEqual(self.config.openssl_version(), "1.0.2g") + assert self.config.openssl_version() == "1.0.2g" def test_current_version(self): self.config.version = (2, 4, 10) self.config._openssl_version = '1.0.2m' - self.assertIn('old', self.config.pick_apache_config()) + assert 'old' in self.config.pick_apache_config() self.config.version = (2, 4, 11) self.config._openssl_version = '1.0.2m' - self.assertIn('current', self.config.pick_apache_config()) + assert 'current' in self.config.pick_apache_config() self.config._openssl_version = '1.0.2a' - self.assertIn('old', self.config.pick_apache_config()) + assert 'old' in self.config.pick_apache_config() def test_openssl_version_warns(self): self.config._openssl_version = '1.0.2a' - self.assertEqual(self.config.openssl_version(), '1.0.2a') + assert self.config.openssl_version() == '1.0.2a' self.config._openssl_version = None with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log: - self.assertEqual(self.config.openssl_version(), None) - self.assertIn("Could not find ssl_module", mock_log.call_args[0][0]) + assert self.config.openssl_version() == None + assert "Could not find ssl_module" in mock_log.call_args[0][0] # When no ssl_module is present at all self.config._openssl_version = None - self.assertNotIn("ssl_module", self.config.parser.modules) + assert "ssl_module" not in self.config.parser.modules with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log: - self.assertEqual(self.config.openssl_version(), None) - self.assertIn("Could not find ssl_module", mock_log.call_args[0][0]) + assert self.config.openssl_version() == None + assert "Could not find ssl_module" in mock_log.call_args[0][0] # When ssl_module is statically linked but --apache-bin not provided self.config._openssl_version = None self.config.options.bin = None self.config.parser.modules['ssl_module'] = None with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log: - self.assertEqual(self.config.openssl_version(), None) - self.assertIn("ssl_module is statically linked but", mock_log.call_args[0][0]) + assert self.config.openssl_version() == None + assert "ssl_module is statically linked but" in mock_log.call_args[0][0] self.config.parser.modules['ssl_module'] = "/fake/path" with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log: # Check that correct logger.warning was printed - self.assertEqual(self.config.openssl_version(), None) - self.assertIn("Unable to read", mock_log.call_args[0][0]) + assert self.config.openssl_version() == None + assert "Unable to read" in mock_log.call_args[0][0] contents_missing_openssl = b"these contents won't match the regex" with mock.patch("certbot_apache._internal.configurator." @@ -1767,13 +1744,13 @@ class InstallSslOptionsConfTest(util.ApacheTest): mock_omf.return_value = contents_missing_openssl with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log: # Check that correct logger.warning was printed - self.assertEqual(self.config.openssl_version(), None) - self.assertIn("Could not find OpenSSL", mock_log.call_args[0][0]) + assert self.config.openssl_version() == None + assert "Could not find OpenSSL" in mock_log.call_args[0][0] def test_open_module_file(self): mock_open = mock.mock_open(read_data="testing 12 3") with mock.patch("builtins.open", mock_open): - self.assertEqual(self.config._open_module_file("/nonsense/"), "testing 12 3") + assert self.config._open_module_file("/nonsense/") == "testing 12 3" if __name__ == "__main__": sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/debian_test.py b/certbot-apache/tests/debian_test.py index 775b542a2..ff343b123 100644 --- a/certbot-apache/tests/debian_test.py +++ b/certbot-apache/tests/debian_test.py @@ -44,7 +44,8 @@ class MultipleVhostsTestDebian(util.ApacheTest): def test_enable_mod_unsupported_dirs(self): shutil.rmtree(os.path.join(self.config.parser.root, "mods-enabled")) - self.assertRaises(errors.NotSupportedError, self.config.enable_mod, "ssl") + with pytest.raises(errors.NotSupportedError): + self.config.enable_mod("ssl") @mock.patch("certbot.util.run_script") @mock.patch("certbot.util.exe_exists") @@ -56,29 +57,29 @@ class MultipleVhostsTestDebian(util.ApacheTest): mock_exe_exists.return_value = True self.config.enable_mod("ssl") - self.assertIn("ssl_module", self.config.parser.modules) - self.assertIn("mod_ssl.c", self.config.parser.modules) + assert "ssl_module" in self.config.parser.modules + assert "mod_ssl.c" in self.config.parser.modules - self.assertIs(mock_run_script.called, True) + assert mock_run_script.called is True def test_deploy_cert_enable_new_vhost(self): # Create ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[0]) self.config.parser.modules["ssl_module"] = None self.config.parser.modules["mod_ssl.c"] = None - self.assertIs(ssl_vhost.enabled, False) + assert ssl_vhost.enabled is False with certbot_util.patch_display_util(): self.config.deploy_cert( "encryption-example.demo", "example/cert.pem", "example/key.pem", "example/cert_chain.pem", "example/fullchain.pem") - self.assertIs(ssl_vhost.enabled, True) + assert ssl_vhost.enabled is True # Make sure that we don't error out if symlink already exists ssl_vhost.enabled = False - self.assertIs(ssl_vhost.enabled, False) + assert ssl_vhost.enabled is False self.config.deploy_cert( "encryption-example.demo", "example/cert.pem", "example/key.pem", "example/cert_chain.pem", "example/fullchain.pem") - self.assertIs(ssl_vhost.enabled, True) + assert ssl_vhost.enabled is True def test_enable_site_failure(self): self.config.parser.root = "/tmp/nonexistent" @@ -86,10 +87,8 @@ class MultipleVhostsTestDebian(util.ApacheTest): mock_dir.return_value = True with mock.patch("certbot.compat.os.path.islink") as mock_link: mock_link.return_value = False - self.assertRaises( - errors.NotSupportedError, - self.config.enable_site, - obj.VirtualHost("asdf", "afsaf", set(), False, False)) + with pytest.raises(errors.NotSupportedError): + self.config.enable_site(obj.VirtualHost("asdf", "afsaf", set(), False, False)) def test_deploy_cert_newssl(self): self.config = util.get_apache_configurator( @@ -108,8 +107,8 @@ class MultipleVhostsTestDebian(util.ApacheTest): self.config.save() # Verify ssl_module was enabled. - self.assertIs(self.vh_truth[1].enabled, True) - self.assertIn("ssl_module", self.config.parser.modules) + assert self.vh_truth[1].enabled is True + assert "ssl_module" in self.config.parser.modules loc_cert = self.config.parser.find_dir( "sslcertificatefile", "example/fullchain.pem", @@ -118,15 +117,13 @@ class MultipleVhostsTestDebian(util.ApacheTest): "sslcertificateKeyfile", "example/key.pem", self.vh_truth[1].path) # Verify one directive was found in the correct file - self.assertEqual(len(loc_cert), 1) - self.assertEqual( - apache_util.get_file_path(loc_cert[0]), - self.vh_truth[1].filep) + assert len(loc_cert) == 1 + assert apache_util.get_file_path(loc_cert[0]) == \ + self.vh_truth[1].filep - self.assertEqual(len(loc_key), 1) - self.assertEqual( - apache_util.get_file_path(loc_key[0]), - self.vh_truth[1].filep) + assert len(loc_key) == 1 + assert apache_util.get_file_path(loc_key[0]) == \ + self.vh_truth[1].filep def test_deploy_cert_newssl_no_fullchain(self): self.config = util.get_apache_configurator( @@ -138,10 +135,10 @@ class MultipleVhostsTestDebian(util.ApacheTest): # Get the default 443 vhost self.config.assoc["random.demo"] = self.vh_truth[1] - self.assertRaises(errors.PluginError, - lambda: self.config.deploy_cert( + with pytest.raises(errors.PluginError): + self.config.deploy_cert( "random.demo", "example/cert.pem", - "example/key.pem")) + "example/key.pem") def test_deploy_cert_old_apache_no_chain(self): self.config = util.get_apache_configurator( @@ -153,10 +150,10 @@ class MultipleVhostsTestDebian(util.ApacheTest): # Get the default 443 vhost self.config.assoc["random.demo"] = self.vh_truth[1] - self.assertRaises(errors.PluginError, - lambda: self.config.deploy_cert( + with pytest.raises(errors.PluginError): + self.config.deploy_cert( "random.demo", "example/cert.pem", - "example/key.pem")) + "example/key.pem") @mock.patch("certbot.util.run_script") @mock.patch("certbot.util.exe_exists") @@ -168,7 +165,7 @@ class MultipleVhostsTestDebian(util.ApacheTest): # This will create an ssl vhost for certbot.demo self.config.choose_vhost("certbot.demo") self.config.enhance("certbot.demo", "staple-ocsp") - self.assertIn("socache_shmcb_module", self.config.parser.modules) + assert "socache_shmcb_module" in self.config.parser.modules @mock.patch("certbot.util.run_script") @mock.patch("certbot.util.exe_exists") @@ -181,7 +178,7 @@ class MultipleVhostsTestDebian(util.ApacheTest): self.config.choose_vhost("certbot.demo") self.config.enhance("certbot.demo", "ensure-http-header", "Strict-Transport-Security") - self.assertIn("headers_module", self.config.parser.modules) + assert "headers_module" in self.config.parser.modules @mock.patch("certbot.util.run_script") @mock.patch("certbot.util.exe_exists") @@ -192,10 +189,10 @@ class MultipleVhostsTestDebian(util.ApacheTest): # This will create an ssl vhost for certbot.demo self.config.choose_vhost("certbot.demo") self.config.enhance("certbot.demo", "redirect") - self.assertIn("rewrite_module", self.config.parser.modules) + assert "rewrite_module" in self.config.parser.modules def test_enable_site_already_enabled(self): - self.assertIs(self.vh_truth[1].enabled, True) + assert self.vh_truth[1].enabled is True self.config.enable_site(self.vh_truth[1]) def test_enable_site_call_parent(self): @@ -205,13 +202,13 @@ class MultipleVhostsTestDebian(util.ApacheTest): vh = self.vh_truth[0] vh.enabled = False self.config.enable_site(vh) - self.assertIs(e_s.called, True) + assert e_s.called is True @mock.patch("certbot.util.exe_exists") def test_enable_mod_no_disable(self, mock_exe_exists): mock_exe_exists.return_value = False - self.assertRaises( - errors.MisconfigurationError, self.config.enable_mod, "ssl") + with pytest.raises(errors.MisconfigurationError): + self.config.enable_mod("ssl") if __name__ == "__main__": sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/display_ops_test.py b/certbot-apache/tests/display_ops_test.py index d730f7c78..613fa42e9 100644 --- a/certbot-apache/tests/display_ops_test.py +++ b/certbot-apache/tests/display_ops_test.py @@ -22,7 +22,7 @@ class SelectVhostMultiTest(unittest.TestCase): self.base_dir, "debian_apache_2_4/multiple_vhosts") def test_select_no_input(self): - self.assertEqual(len(select_vhost_multiple([])), 0) + assert len(select_vhost_multiple([])) == 0 @certbot_util.patch_display_util() def test_select_correct(self, mock_util): @@ -32,15 +32,15 @@ class SelectVhostMultiTest(unittest.TestCase): vhs = select_vhost_multiple([self.vhosts[3], self.vhosts[2], self.vhosts[1]]) - self.assertIn(self.vhosts[2], vhs) - self.assertIn(self.vhosts[3], vhs) - self.assertNotIn(self.vhosts[1], vhs) + assert self.vhosts[2] in vhs + assert self.vhosts[3] in vhs + assert self.vhosts[1] not in vhs @certbot_util.patch_display_util() def test_select_cancel(self, mock_util): mock_util().checklist.return_value = (display_util.CANCEL, "whatever") vhs = select_vhost_multiple([self.vhosts[2], self.vhosts[3]]) - self.assertEqual(vhs, []) + assert vhs == [] class SelectVhostTest(unittest.TestCase): @@ -59,7 +59,7 @@ class SelectVhostTest(unittest.TestCase): @certbot_util.patch_display_util() def test_successful_choice(self, mock_util): mock_util().menu.return_value = (display_util.OK, 3) - self.assertEqual(self.vhosts[3], self._call(self.vhosts)) + assert self.vhosts[3] == self._call(self.vhosts) @certbot_util.patch_display_util() def test_noninteractive(self, mock_util): @@ -67,7 +67,7 @@ class SelectVhostTest(unittest.TestCase): try: self._call(self.vhosts) except errors.MissingCommandlineFlag as e: - self.assertIn("vhost ambiguity", str(e)) + assert "vhost ambiguity" in str(e) @certbot_util.patch_display_util() def test_more_info_cancel(self, mock_util): @@ -75,10 +75,10 @@ class SelectVhostTest(unittest.TestCase): (display_util.CANCEL, -1), ] - self.assertIsNone(self._call(self.vhosts)) + assert self._call(self.vhosts) is None def test_no_vhosts(self): - self.assertIsNone(self._call([])) + assert self._call([]) is None @mock.patch("certbot_apache._internal.display_ops.display_util") @mock.patch("certbot_apache._internal.display_ops.logger") @@ -87,7 +87,7 @@ class SelectVhostTest(unittest.TestCase): mock_display_util.menu.return_value = (display_util.OK, 0) self._call(self.vhosts) - self.assertEqual(mock_logger.debug.call_count, 1) + assert mock_logger.debug.call_count == 1 @certbot_util.patch_display_util() def test_multiple_names(self, mock_util): @@ -99,7 +99,7 @@ class SelectVhostTest(unittest.TestCase): False, False, "wildcard.com", {"*.wildcard.com"})) - self.assertEqual(self.vhosts[5], self._call(self.vhosts)) + assert self.vhosts[5] == self._call(self.vhosts) if __name__ == "__main__": diff --git a/certbot-apache/tests/dualnode_test.py b/certbot-apache/tests/dualnode_test.py index a3e28d09e..2ce7fb6c7 100644 --- a/certbot-apache/tests/dualnode_test.py +++ b/certbot-apache/tests/dualnode_test.py @@ -5,6 +5,7 @@ from unittest import mock from certbot_apache._internal import assertions from certbot_apache._internal import augeasparser from certbot_apache._internal import dualparser +import pytest class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public-methods @@ -49,20 +50,20 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- primary=self.block.secondary, secondary=self.block.primary) # Switched around - self.assertEqual(cnode.primary, self.comment.secondary) - self.assertEqual(cnode.secondary, self.comment.primary) - self.assertEqual(dnode.primary, self.directive.secondary) - self.assertEqual(dnode.secondary, self.directive.primary) - self.assertEqual(bnode.primary, self.block.secondary) - self.assertEqual(bnode.secondary, self.block.primary) + assert cnode.primary == self.comment.secondary + assert cnode.secondary == self.comment.primary + assert dnode.primary == self.directive.secondary + assert dnode.secondary == self.directive.primary + assert bnode.primary == self.block.secondary + assert bnode.secondary == self.block.primary def test_set_params(self): params = ("first", "second") self.directive.primary.set_parameters = mock.Mock() self.directive.secondary.set_parameters = mock.Mock() self.directive.set_parameters(params) - self.assertIs(self.directive.primary.set_parameters.called, True) - self.assertIs(self.directive.secondary.set_parameters.called, True) + assert self.directive.primary.set_parameters.called is True + assert self.directive.secondary.set_parameters.called is True def test_set_parameters(self): pparams = mock.MagicMock() @@ -72,8 +73,8 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- self.directive.primary.set_parameters = pparams self.directive.secondary.set_parameters = sparams self.directive.set_parameters(("param", "seq")) - self.assertIs(pparams.called, True) - self.assertIs(sparams.called, True) + assert pparams.called is True + assert sparams.called is True def test_delete_child(self): pdel = mock.MagicMock() @@ -81,8 +82,8 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- self.block.primary.delete_child = pdel self.block.secondary.delete_child = sdel self.block.delete_child(self.comment) - self.assertIs(pdel.called, True) - self.assertIs(sdel.called, True) + assert pdel.called is True + assert sdel.called is True def test_unsaved_files(self): puns = mock.MagicMock() @@ -92,13 +93,13 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- self.block.primary.unsaved_files = puns self.block.secondary.unsaved_files = suns self.block.unsaved_files() - self.assertIs(puns.called, True) - self.assertIs(suns.called, True) + assert puns.called is True + assert suns.called is True def test_getattr_equality(self): self.directive.primary.variableexception = "value" self.directive.secondary.variableexception = "not_value" - with self.assertRaises(AssertionError): + with pytest.raises(AssertionError): _ = self.directive.variableexception self.directive.primary.variable = "value" @@ -117,7 +118,7 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- self.comment.primary.dirty = False self.comment.secondary.dirty = True - with self.assertRaises(AssertionError): + with pytest.raises(AssertionError): assertions.assertEqual(self.comment.primary, self.comment.secondary) def test_parsernode_filepath_assert(self): @@ -127,7 +128,7 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- self.comment.primary.filepath = "first" self.comment.secondary.filepath = "second" - with self.assertRaises(AssertionError): + with pytest.raises(AssertionError): assertions.assertEqual(self.comment.primary, self.comment.secondary) def test_add_child_block(self): @@ -136,8 +137,8 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- self.block.primary.add_child_block = mock_first self.block.secondary.add_child_block = mock_second self.block.add_child_block("Block") - self.assertIs(mock_first.called, True) - self.assertIs(mock_second.called, True) + assert mock_first.called is True + assert mock_second.called is True def test_add_child_directive(self): mock_first = mock.MagicMock(return_value=self.directive.primary) @@ -145,8 +146,8 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- self.block.primary.add_child_directive = mock_first self.block.secondary.add_child_directive = mock_second self.block.add_child_directive("Directive") - self.assertIs(mock_first.called, True) - self.assertIs(mock_second.called, True) + assert mock_first.called is True + assert mock_second.called is True def test_add_child_comment(self): mock_first = mock.MagicMock(return_value=self.comment.primary) @@ -154,8 +155,8 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- self.block.primary.add_child_comment = mock_first self.block.secondary.add_child_comment = mock_second self.block.add_child_comment("Comment") - self.assertIs(mock_first.called, True) - self.assertIs(mock_second.called, True) + assert mock_first.called is True + assert mock_second.called is True def test_find_comments(self): pri_comments = [augeasparser.AugeasCommentNode(comment="some comment", @@ -179,9 +180,9 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- # Check that every comment response is represented in the list of # DualParserNode instances. for p in p_dcoms: - self.assertIn(p, p_coms) + assert p in p_coms for s in s_dcoms: - self.assertIn(s, s_coms) + assert s in s_coms def test_find_blocks_first_passing(self): youshallnotpass = [augeasparser.AugeasBlockNode(name="notpassing", @@ -203,8 +204,8 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- assertions.assertEqual(block.primary, block.secondary) except AssertionError: # pragma: no cover self.fail("Assertion should have passed") - self.assertIs(assertions.isPassDirective(block.primary), True) - self.assertIs(assertions.isPassDirective(block.secondary), False) + assert assertions.isPassDirective(block.primary) is True + assert assertions.isPassDirective(block.secondary) is False def test_find_blocks_second_passing(self): youshallnotpass = [augeasparser.AugeasBlockNode(name="notpassing", @@ -226,8 +227,8 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- assertions.assertEqual(block.primary, block.secondary) except AssertionError: # pragma: no cover self.fail("Assertion should have passed") - self.assertIs(assertions.isPassDirective(block.primary), False) - self.assertIs(assertions.isPassDirective(block.secondary), True) + assert assertions.isPassDirective(block.primary) is False + assert assertions.isPassDirective(block.secondary) is True def test_find_dirs_first_passing(self): notpassing = [augeasparser.AugeasDirectiveNode(name="notpassing", @@ -249,8 +250,8 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- assertions.assertEqual(directive.primary, directive.secondary) except AssertionError: # pragma: no cover self.fail("Assertion should have passed") - self.assertIs(assertions.isPassDirective(directive.primary), True) - self.assertIs(assertions.isPassDirective(directive.secondary), False) + assert assertions.isPassDirective(directive.primary) is True + assert assertions.isPassDirective(directive.secondary) is False def test_find_dirs_second_passing(self): notpassing = [augeasparser.AugeasDirectiveNode(name="notpassing", @@ -272,8 +273,8 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- assertions.assertEqual(directive.primary, directive.secondary) except AssertionError: # pragma: no cover self.fail("Assertion should have passed") - self.assertIs(assertions.isPassDirective(directive.primary), False) - self.assertIs(assertions.isPassDirective(directive.secondary), True) + assert assertions.isPassDirective(directive.primary) is False + assert assertions.isPassDirective(directive.secondary) is True def test_find_coms_first_passing(self): notpassing = [augeasparser.AugeasCommentNode(comment="notpassing", @@ -295,8 +296,8 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- assertions.assertEqual(comment.primary, comment.secondary) except AssertionError: # pragma: no cover self.fail("Assertion should have passed") - self.assertIs(assertions.isPassComment(comment.primary), True) - self.assertIs(assertions.isPassComment(comment.secondary), False) + assert assertions.isPassComment(comment.primary) is True + assert assertions.isPassComment(comment.secondary) is False def test_find_coms_second_passing(self): notpassing = [augeasparser.AugeasCommentNode(comment="notpassing", @@ -318,8 +319,8 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- assertions.assertEqual(comment.primary, comment.secondary) except AssertionError: # pragma: no cover self.fail("Assertion should have passed") - self.assertIs(assertions.isPassComment(comment.primary), False) - self.assertIs(assertions.isPassComment(comment.secondary), True) + assert assertions.isPassComment(comment.primary) is False + assert assertions.isPassComment(comment.secondary) is True def test_find_blocks_no_pass_equal(self): notpassing1 = [augeasparser.AugeasBlockNode(name="notpassing", @@ -338,8 +339,8 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- blocks = self.block.find_blocks("anything") for block in blocks: with self.subTest(block=block): - self.assertEqual(block.primary, block.secondary) - self.assertIsNot(block.primary, block.secondary) + assert block.primary == block.secondary + assert block.primary is not block.secondary def test_find_dirs_no_pass_equal(self): notpassing1 = [augeasparser.AugeasDirectiveNode(name="notpassing", @@ -358,8 +359,8 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- directives = self.block.find_directives("anything") for directive in directives: with self.subTest(directive=directive): - self.assertEqual(directive.primary, directive.secondary) - self.assertIsNot(directive.primary, directive.secondary) + assert directive.primary == directive.secondary + assert directive.primary is not directive.secondary def test_find_comments_no_pass_equal(self): notpassing1 = [augeasparser.AugeasCommentNode(comment="notpassing", @@ -378,8 +379,8 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- comments = self.block.find_comments("anything") for comment in comments: with self.subTest(comment=comment): - self.assertEqual(comment.primary, comment.secondary) - self.assertIsNot(comment.primary, comment.secondary) + assert comment.primary == comment.secondary + assert comment.primary is not comment.secondary def test_find_blocks_no_pass_notequal(self): notpassing1 = [augeasparser.AugeasBlockNode(name="notpassing", @@ -395,7 +396,7 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- self.block.primary.find_blocks = find_blocks_primary self.block.secondary.find_blocks = find_blocks_secondary - with self.assertRaises(AssertionError): + with pytest.raises(AssertionError): _ = self.block.find_blocks("anything") def test_parsernode_notequal(self): @@ -411,9 +412,9 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- ancestor=self.block, filepath="/path/to/whatever", metadata=self.metadata) - self.assertNotEqual(self.block, ne_block) - self.assertNotEqual(self.directive, ne_directive) - self.assertNotEqual(self.comment, ne_comment) + assert self.block != ne_block + assert self.directive != ne_directive + assert self.comment != ne_comment def test_parsed_paths(self): mock_p = mock.MagicMock(return_value=['/path/file.conf', @@ -423,15 +424,15 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- self.block.primary.parsed_paths = mock_p self.block.secondary.parsed_paths = mock_s self.block.parsed_paths() - self.assertIs(mock_p.called, True) - self.assertIs(mock_s.called, True) + assert mock_p.called is True + assert mock_s.called is True def test_parsed_paths_error(self): mock_p = mock.MagicMock(return_value=['/path/file.conf']) mock_s = mock.MagicMock(return_value=['/path/*.conf', '/another/path']) self.block.primary.parsed_paths = mock_p self.block.secondary.parsed_paths = mock_s - with self.assertRaises(AssertionError): + with pytest.raises(AssertionError): self.block.parsed_paths() def test_find_ancestors(self): @@ -440,5 +441,5 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- self.block.primary.find_ancestors = primarymock self.block.secondary.find_ancestors = secondarymock self.block.find_ancestors("anything") - self.assertIs(primarymock.called, True) - self.assertIs(secondarymock.called, True) + assert primarymock.called is True + assert secondarymock.called is True diff --git a/certbot-apache/tests/entrypoint_test.py b/certbot-apache/tests/entrypoint_test.py index c6dbd53b2..ef5013555 100644 --- a/certbot-apache/tests/entrypoint_test.py +++ b/certbot-apache/tests/entrypoint_test.py @@ -24,8 +24,8 @@ class EntryPointTest(unittest.TestCase): elif distro == 'fedora': return_value = ('fedora', '29') mock_info.return_value = return_value - self.assertEqual(entrypoint.get_configurator(), - entrypoint.OVERRIDE_CLASSES[distro]) + assert entrypoint.get_configurator() == \ + entrypoint.OVERRIDE_CLASSES[distro] def test_nonexistent_like(self): with mock.patch("certbot.util.get_os_info") as mock_info: @@ -33,16 +33,16 @@ class EntryPointTest(unittest.TestCase): with mock.patch("certbot.util.get_systemd_os_like") as mock_like: for like in entrypoint.OVERRIDE_CLASSES: mock_like.return_value = [like] - self.assertEqual(entrypoint.get_configurator(), - entrypoint.OVERRIDE_CLASSES[like]) + assert entrypoint.get_configurator() == \ + entrypoint.OVERRIDE_CLASSES[like] def test_nonexistent_generic(self): with mock.patch("certbot.util.get_os_info") as mock_info: mock_info.return_value = ("nonexistent", "irrelevant") with mock.patch("certbot.util.get_systemd_os_like") as mock_like: mock_like.return_value = ["unknown"] - self.assertEqual(entrypoint.get_configurator(), - configurator.ApacheConfigurator) + assert entrypoint.get_configurator() == \ + configurator.ApacheConfigurator if __name__ == "__main__": diff --git a/certbot-apache/tests/fedora_test.py b/certbot-apache/tests/fedora_test.py index faf6e8ccc..353352143 100644 --- a/certbot-apache/tests/fedora_test.py +++ b/certbot-apache/tests/fedora_test.py @@ -55,7 +55,7 @@ class FedoraRestartTest(util.ApacheTest): self.temp_dir, "centos7_apache/apache") def _run_fedora_test(self): - self.assertIsInstance(self.config, override_fedora.FedoraConfigurator) + assert isinstance(self.config, override_fedora.FedoraConfigurator) self.config.config_test() def test_fedora_restart_error(self): @@ -65,8 +65,8 @@ class FedoraRestartTest(util.ApacheTest): mock_test.side_effect = [errors.MisconfigurationError, ''] with mock.patch("certbot.util.run_script") as mock_run: mock_run.side_effect = errors.SubprocessError - self.assertRaises(errors.MisconfigurationError, - self._run_fedora_test) + with pytest.raises(errors.MisconfigurationError): + self._run_fedora_test() def test_fedora_restart(self): c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test" @@ -75,9 +75,9 @@ class FedoraRestartTest(util.ApacheTest): # First call raises error, second doesn't mock_test.side_effect = [errors.MisconfigurationError, ''] self._run_fedora_test() - self.assertEqual(mock_test.call_count, 2) - self.assertEqual(mock_run.call_args[0][0], - ['systemctl', 'restart', 'httpd']) + assert mock_test.call_count == 2 + assert mock_run.call_args[0][0] == \ + ['systemctl', 'restart', 'httpd'] class MultipleVhostsTestFedora(util.ApacheTest): @@ -100,7 +100,7 @@ class MultipleVhostsTestFedora(util.ApacheTest): self.temp_dir, "centos7_apache/apache") def test_get_parser(self): - self.assertIsInstance(self.config.parser, override_fedora.FedoraParser) + assert isinstance(self.config.parser, override_fedora.FedoraParser) @mock.patch("certbot_apache._internal.apache_util._get_runtime_cfg") def test_opportunistic_httpd_runtime_parsing(self, mock_get): @@ -130,22 +130,23 @@ class MultipleVhostsTestFedora(util.ApacheTest): mock_osi.return_value = ("fedora", "29") self.config.parser.update_runtime_variables() - self.assertEqual(mock_get.call_count, 3) - self.assertEqual(len(self.config.parser.modules), 4) - self.assertEqual(len(self.config.parser.variables), 2) - self.assertIn("TEST2", self.config.parser.variables) - self.assertIn("mod_another.c", self.config.parser.modules) + assert mock_get.call_count == 3 + assert len(self.config.parser.modules) == 4 + assert len(self.config.parser.variables) == 2 + assert "TEST2" in self.config.parser.variables + assert "mod_another.c" in self.config.parser.modules @mock.patch("certbot_apache._internal.configurator.util.run_script") def test_get_version(self, mock_run_script): mock_run_script.return_value = ('', None) - self.assertRaises(errors.PluginError, self.config.get_version) - self.assertEqual(mock_run_script.call_args[0][0][0], 'httpd') + with pytest.raises(errors.PluginError): + self.config.get_version() + assert mock_run_script.call_args[0][0][0] == 'httpd' def test_get_virtual_hosts(self): """Make sure all vhosts are being properly found.""" vhs = self.config.get_virtual_hosts() - self.assertEqual(len(vhs), 2) + assert len(vhs) == 2 found = 0 for vhost in vhs: @@ -155,7 +156,7 @@ class MultipleVhostsTestFedora(util.ApacheTest): break else: raise Exception("Missed: %s" % vhost) # pragma: no cover - self.assertEqual(found, 2) + assert found == 2 @mock.patch("certbot_apache._internal.apache_util._get_runtime_cfg") def test_get_sysconfig_vars(self, mock_cfg): @@ -171,25 +172,26 @@ class MultipleVhostsTestFedora(util.ApacheTest): mock_osi.return_value = ("fedora", "29") self.config.parser.update_runtime_variables() - self.assertIn("mock_define", self.config.parser.variables) - self.assertIn("mock_define_too", self.config.parser.variables) - self.assertIn("mock_value", self.config.parser.variables) - self.assertEqual("TRUE", self.config.parser.variables["mock_value"]) - self.assertIn("MOCK_NOSEP", self.config.parser.variables) - self.assertEqual("NOSEP_VAL", self.config.parser.variables["NOSEP_TWO"]) + assert "mock_define" in self.config.parser.variables + assert "mock_define_too" in self.config.parser.variables + assert "mock_value" in self.config.parser.variables + assert "TRUE" == self.config.parser.variables["mock_value"] + assert "MOCK_NOSEP" in self.config.parser.variables + assert "NOSEP_VAL" == self.config.parser.variables["NOSEP_TWO"] @mock.patch("certbot_apache._internal.configurator.util.run_script") def test_alt_restart_works(self, mock_run_script): mock_run_script.side_effect = [None, errors.SubprocessError, None] self.config.restart() - self.assertEqual(mock_run_script.call_count, 3) + assert mock_run_script.call_count == 3 @mock.patch("certbot_apache._internal.configurator.util.run_script") def test_alt_restart_errors(self, mock_run_script): mock_run_script.side_effect = [None, errors.SubprocessError, errors.SubprocessError] - self.assertRaises(errors.MisconfigurationError, self.config.restart) + with pytest.raises(errors.MisconfigurationError): + self.config.restart() if __name__ == "__main__": diff --git a/certbot-apache/tests/gentoo_test.py b/certbot-apache/tests/gentoo_test.py index 201cccb85..6399797ed 100644 --- a/certbot-apache/tests/gentoo_test.py +++ b/certbot-apache/tests/gentoo_test.py @@ -62,12 +62,12 @@ class MultipleVhostsTestGentoo(util.ApacheTest): self.temp_dir, "gentoo_apache/apache") def test_get_parser(self): - self.assertIsInstance(self.config.parser, override_gentoo.GentooParser) + assert isinstance(self.config.parser, override_gentoo.GentooParser) def test_get_virtual_hosts(self): """Make sure all vhosts are being properly found.""" vhs = self.config.get_virtual_hosts() - self.assertEqual(len(vhs), 3) + assert len(vhs) == 3 found = 0 for vhost in vhs: @@ -77,7 +77,7 @@ class MultipleVhostsTestGentoo(util.ApacheTest): break else: raise Exception("Missed: %s" % vhost) # pragma: no cover - self.assertEqual(found, 3) + assert found == 3 def test_get_sysconfig_vars(self): """Make sure we read the Gentoo APACHE2_OPTS variable correctly""" @@ -89,7 +89,7 @@ class MultipleVhostsTestGentoo(util.ApacheTest): with mock.patch("certbot_apache._internal.override_gentoo.GentooParser.update_modules"): self.config.parser.update_runtime_variables() for define in defines: - self.assertIn(define, self.config.parser.variables) + assert define in self.config.parser.variables @mock.patch("certbot_apache._internal.apache_util.parse_from_subprocess") def test_no_binary_configdump(self, mock_subprocess): @@ -99,11 +99,11 @@ class MultipleVhostsTestGentoo(util.ApacheTest): with mock.patch("certbot_apache._internal.override_gentoo.GentooParser.update_modules"): self.config.parser.update_runtime_variables() self.config.parser.reset_modules() - self.assertIs(mock_subprocess.called, False) + assert mock_subprocess.called is False self.config.parser.update_runtime_variables() self.config.parser.reset_modules() - self.assertIs(mock_subprocess.called, True) + assert mock_subprocess.called is True @mock.patch("certbot_apache._internal.apache_util._get_runtime_cfg") def test_opportunistic_httpd_runtime_parsing(self, mock_get): @@ -125,15 +125,15 @@ class MultipleVhostsTestGentoo(util.ApacheTest): mock_osi.return_value = ("gentoo", "123") self.config.parser.update_runtime_variables() - self.assertEqual(mock_get.call_count, 1) - self.assertEqual(len(self.config.parser.modules), 4) - self.assertIn("mod_another.c", self.config.parser.modules) + assert mock_get.call_count == 1 + assert len(self.config.parser.modules) == 4 + assert "mod_another.c" in self.config.parser.modules @mock.patch("certbot_apache._internal.configurator.util.run_script") def test_alt_restart_works(self, mock_run_script): mock_run_script.side_effect = [None, errors.SubprocessError, None] self.config.restart() - self.assertEqual(mock_run_script.call_count, 3) + assert mock_run_script.call_count == 3 if __name__ == "__main__": sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-apache/tests/http_01_test.py b/certbot-apache/tests/http_01_test.py index 5fbf52bf5..b73be6f4f 100644 --- a/certbot-apache/tests/http_01_test.py +++ b/certbot-apache/tests/http_01_test.py @@ -50,7 +50,7 @@ class ApacheHttp01Test(util.ApacheTest): self.http = ApacheHttp01(self.config) def test_empty_perform(self): - self.assertEqual(len(self.http.perform()), 0) + assert len(self.http.perform()) == 0 @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.enable_mod") def test_enable_modules_apache_2_4(self, mock_enmod): @@ -58,7 +58,7 @@ class ApacheHttp01Test(util.ApacheTest): del self.config.parser.modules["mod_authz_host.c"] enmod_calls = self.common_enable_modules_test(mock_enmod) - self.assertEqual(enmod_calls[0][0][0], "authz_core") + assert enmod_calls[0][0][0] == "authz_core" def common_enable_modules_test(self, mock_enmod): """Tests enabling mod_rewrite and other modules.""" @@ -67,7 +67,7 @@ class ApacheHttp01Test(util.ApacheTest): self.http.prepare_http01_modules() - self.assertIs(mock_enmod.called, True) + assert mock_enmod.called is True calls = mock_enmod.call_args_list other_calls = [] for call in calls: @@ -75,7 +75,7 @@ class ApacheHttp01Test(util.ApacheTest): other_calls.append(call) # If these lists are equal, we never enabled mod_rewrite - self.assertNotEqual(calls, other_calls) + assert calls != other_calls return other_calls def test_same_vhost(self): @@ -106,7 +106,7 @@ class ApacheHttp01Test(util.ApacheTest): def test_configure_multiple_vhosts(self): vhosts = [v for v in self.config.vhosts if "duplicate.example.com" in v.get_names()] - self.assertEqual(len(vhosts), 2) + assert len(vhosts) == 2 achalls = [ achallenges.KeyAuthorizationAnnotatedChallenge( challb=acme_util.chall_to_challb( @@ -131,7 +131,8 @@ class ApacheHttp01Test(util.ApacheTest): for achall in self.achalls: self.http.add_chall(achall) self.config.config.http01_port = 12345 - self.assertRaises(errors.PluginError, self.http.perform) + with pytest.raises(errors.PluginError): + self.http.perform() def test_perform_1_achall_apache_2_4(self): self.combinations_perform_test(num_achalls=1, minor_version=4) @@ -155,7 +156,7 @@ class ApacheHttp01Test(util.ApacheTest): matches = self.config.parser.find_dir( "Include", vhosts[0].filep, get_aug_path(self.config.parser.loc["default"])) - self.assertEqual(len(matches), 1) + assert len(matches) == 1 def combinations_perform_test(self, num_achalls, minor_version): """Test perform with the given achall count and Apache version.""" @@ -167,16 +168,16 @@ class ApacheHttp01Test(util.ApacheTest): def common_perform_test(self, achalls, vhosts): """Tests perform with the given achalls.""" challenge_dir = self.http.challenge_dir - self.assertIs(os.path.exists(challenge_dir), False) + assert os.path.exists(challenge_dir) is False for achall in achalls: self.http.add_chall(achall) expected_response = [ achall.response(self.account_key) for achall in achalls] - self.assertEqual(self.http.perform(), expected_response) + assert self.http.perform() == expected_response - self.assertIs(os.path.isdir(self.http.challenge_dir), True) - self.assertIs(filesystem.has_min_permissions(self.http.challenge_dir, 0o755), True) + assert os.path.isdir(self.http.challenge_dir) is True + assert filesystem.has_min_permissions(self.http.challenge_dir, 0o755) is True self._test_challenge_conf() for achall in achalls: @@ -186,19 +187,20 @@ class ApacheHttp01Test(util.ApacheTest): matches = self.config.parser.find_dir("Include", self.http.challenge_conf_pre, vhost.path) - self.assertEqual(len(matches), 1) + assert len(matches) == 1 matches = self.config.parser.find_dir("Include", self.http.challenge_conf_post, vhost.path) - self.assertEqual(len(matches), 1) + assert len(matches) == 1 - self.assertIs(os.path.exists(challenge_dir), True) + assert os.path.exists(challenge_dir) is True @mock.patch("certbot_apache._internal.http_01.filesystem.makedirs") def test_failed_makedirs(self, mock_makedirs): mock_makedirs.side_effect = OSError(errno.EACCES, "msg") self.http.add_chall(self.achalls[0]) - self.assertRaises(errors.PluginError, self.http.perform) + with pytest.raises(errors.PluginError): + self.http.perform() def _test_challenge_conf(self): with open(self.http.challenge_conf_pre) as f: @@ -207,19 +209,19 @@ class ApacheHttp01Test(util.ApacheTest): with open(self.http.challenge_conf_post) as f: post_conf_contents = f.read() - self.assertIn("RewriteEngine on", pre_conf_contents) - self.assertIn("RewriteRule", pre_conf_contents) + assert "RewriteEngine on" in pre_conf_contents + assert "RewriteRule" in pre_conf_contents - self.assertIn(self.http.challenge_dir, post_conf_contents) - self.assertIn("Require all granted", post_conf_contents) + assert self.http.challenge_dir in post_conf_contents + assert "Require all granted" in post_conf_contents def _test_challenge_file(self, achall): name = os.path.join(self.http.challenge_dir, achall.chall.encode("token")) validation = achall.validation(self.account_key) - self.assertIs(filesystem.has_min_permissions(name, 0o644), True) + assert filesystem.has_min_permissions(name, 0o644) is True with open(name, 'rb') as f: - self.assertEqual(f.read(), validation.encode()) + assert f.read() == validation.encode() if __name__ == "__main__": diff --git a/certbot-apache/tests/obj_test.py b/certbot-apache/tests/obj_test.py index a2053dc43..16a71ba62 100644 --- a/certbot-apache/tests/obj_test.py +++ b/certbot-apache/tests/obj_test.py @@ -26,18 +26,18 @@ class VirtualHostTest(unittest.TestCase): "fp", "vhp", {self.addr2}, False, False, "localhost") def test_repr(self): - self.assertEqual(repr(self.addr2), - "certbot_apache._internal.obj.Addr(('127.0.0.1', '443'))") + assert repr(self.addr2) == \ + "certbot_apache._internal.obj.Addr(('127.0.0.1', '443'))" def test_eq(self): - self.assertEqual(self.vhost1b, self.vhost1) - self.assertNotEqual(self.vhost1, self.vhost2) - self.assertEqual(str(self.vhost1b), str(self.vhost1)) - self.assertNotEqual(self.vhost1b, 1234) + assert self.vhost1b == self.vhost1 + assert self.vhost1 != self.vhost2 + assert str(self.vhost1b) == str(self.vhost1) + assert self.vhost1b != 1234 def test_ne(self): - self.assertNotEqual(self.vhost1, self.vhost2) - self.assertEqual(self.vhost1, self.vhost1b) + assert self.vhost1 != self.vhost2 + assert self.vhost1 == self.vhost1b def test_conflicts(self): from certbot_apache._internal.obj import Addr @@ -47,14 +47,14 @@ class VirtualHostTest(unittest.TestCase): "fp", "vhp", {Addr.fromstring("*:443"), Addr.fromstring("1.2.3.4:443")}, False, False) - self.assertIs(complex_vh.conflicts([self.addr1]), True) - self.assertIs(complex_vh.conflicts([self.addr2]), True) - self.assertIs(complex_vh.conflicts([self.addr_default]), False) + assert complex_vh.conflicts([self.addr1]) is True + assert complex_vh.conflicts([self.addr2]) is True + assert complex_vh.conflicts([self.addr_default]) is False - self.assertIs(self.vhost1.conflicts([self.addr2]), True) - self.assertIs(self.vhost1.conflicts([self.addr_default]), False) + assert self.vhost1.conflicts([self.addr2]) is True + assert self.vhost1.conflicts([self.addr_default]) is False - self.assertIs(self.vhost2.conflicts([self.addr1, self.addr_default]), False) + assert self.vhost2.conflicts([self.addr1, self.addr_default]) is False def test_same_server(self): from certbot_apache._internal.obj import VirtualHost @@ -69,12 +69,12 @@ class VirtualHostTest(unittest.TestCase): "fp", "vhp", {self.addr2, self.addr_default}, False, False, None) - self.assertIs(self.vhost1.same_server(self.vhost2), True) - self.assertIs(no_name1.same_server(no_name2), True) + assert self.vhost1.same_server(self.vhost2) is True + assert no_name1.same_server(no_name2) is True - self.assertIs(self.vhost1.same_server(no_name1), False) - self.assertIs(no_name1.same_server(no_name3), False) - self.assertIs(no_name1.same_server(no_name4), False) + assert self.vhost1.same_server(no_name1) is False + assert no_name1.same_server(no_name3) is False + assert no_name1.same_server(no_name4) is False class AddrTest(unittest.TestCase): @@ -90,53 +90,50 @@ class AddrTest(unittest.TestCase): self.addr_default = Addr.fromstring("_default_:443") def test_wildcard(self): - self.assertIs(self.addr.is_wildcard(), False) - self.assertIs(self.addr1.is_wildcard(), True) - self.assertIs(self.addr2.is_wildcard(), True) + assert self.addr.is_wildcard() is False + assert self.addr1.is_wildcard() is True + assert self.addr2.is_wildcard() is True def test_get_sni_addr(self): from certbot_apache._internal.obj import Addr - self.assertEqual( - self.addr.get_sni_addr("443"), Addr.fromstring("*:443")) - self.assertEqual( - self.addr.get_sni_addr("225"), Addr.fromstring("*:225")) - self.assertEqual( - self.addr1.get_sni_addr("443"), Addr.fromstring("127.0.0.1")) + assert self.addr.get_sni_addr("443") == Addr.fromstring("*:443") + assert self.addr.get_sni_addr("225") == Addr.fromstring("*:225") + assert self.addr1.get_sni_addr("443") == Addr.fromstring("127.0.0.1") def test_conflicts(self): # Note: Defined IP is more important than defined port in match - self.assertIs(self.addr.conflicts(self.addr1), True) - self.assertIs(self.addr.conflicts(self.addr2), True) - self.assertIs(self.addr.conflicts(self.addr_defined), True) - self.assertIs(self.addr.conflicts(self.addr_default), False) + assert self.addr.conflicts(self.addr1) is True + assert self.addr.conflicts(self.addr2) is True + assert self.addr.conflicts(self.addr_defined) is True + assert self.addr.conflicts(self.addr_default) is False - self.assertIs(self.addr1.conflicts(self.addr), False) - self.assertIs(self.addr1.conflicts(self.addr_defined), True) - self.assertIs(self.addr1.conflicts(self.addr_default), False) + assert self.addr1.conflicts(self.addr) is False + assert self.addr1.conflicts(self.addr_defined) is True + assert self.addr1.conflicts(self.addr_default) is False - self.assertIs(self.addr_defined.conflicts(self.addr1), False) - self.assertIs(self.addr_defined.conflicts(self.addr2), False) - self.assertIs(self.addr_defined.conflicts(self.addr), False) - self.assertIs(self.addr_defined.conflicts(self.addr_default), False) + assert self.addr_defined.conflicts(self.addr1) is False + assert self.addr_defined.conflicts(self.addr2) is False + assert self.addr_defined.conflicts(self.addr) is False + assert self.addr_defined.conflicts(self.addr_default) is False - self.assertIs(self.addr_default.conflicts(self.addr), True) - self.assertIs(self.addr_default.conflicts(self.addr1), True) - self.assertIs(self.addr_default.conflicts(self.addr_defined), True) + assert self.addr_default.conflicts(self.addr) is True + assert self.addr_default.conflicts(self.addr1) is True + assert self.addr_default.conflicts(self.addr_defined) is True # Self test - self.assertIs(self.addr.conflicts(self.addr), True) - self.assertIs(self.addr1.conflicts(self.addr1), True) + assert self.addr.conflicts(self.addr) is True + assert self.addr1.conflicts(self.addr1) is True # This is a tricky one... - self.assertIs(self.addr1.conflicts(self.addr2), True) + assert self.addr1.conflicts(self.addr2) is True def test_equal(self): - self.assertEqual(self.addr1, self.addr2) - self.assertNotEqual(self.addr, self.addr1) - self.assertNotEqual(self.addr, 123) + assert self.addr1 == self.addr2 + assert self.addr != self.addr1 + assert self.addr != 123 def test_not_equal(self): - self.assertEqual(self.addr1, self.addr2) - self.assertNotEqual(self.addr, self.addr1) + assert self.addr1 == self.addr2 + assert self.addr != self.addr1 if __name__ == "__main__": diff --git a/certbot-apache/tests/parser_test.py b/certbot-apache/tests/parser_test.py index a5950804c..b4d13c78e 100644 --- a/certbot-apache/tests/parser_test.py +++ b/certbot-apache/tests/parser_test.py @@ -25,14 +25,15 @@ class BasicParserTest(util.ParserTest): def test_bad_parse(self): self.parser.parse_file(os.path.join(self.parser.root, "conf-available", "bad_conf_file.conf")) - self.assertRaises( - errors.PluginError, self.parser.check_parsing_errors, "httpd.aug") + with pytest.raises(errors.PluginError): + self.parser.check_parsing_errors("httpd.aug") def test_bad_save(self): mock_save = mock.Mock() mock_save.side_effect = IOError self.parser.aug.save = mock_save - self.assertRaises(errors.PluginError, self.parser.unsaved_files) + with pytest.raises(errors.PluginError): + self.parser.unsaved_files() @mock.patch("certbot_apache._internal.parser.logger") def test_bad_save_errors(self, mock_logger): @@ -40,7 +41,8 @@ class BasicParserTest(util.ParserTest): self.parser.aug.set("/augeas/load/Httpd/incl[last()]", nx_path) self.parser.add_dir(f"/files{nx_path}", "AddDirective", "test") - self.assertRaises(IOError, self.parser.save, {}) + with pytest.raises(IOError): + self.parser.save({}) mock_logger.error.assert_called_with( 'Unable to save files: %s.%s', '/non/existent/path.conf', mock.ANY) mock_logger.debug.assert_called_with( @@ -51,16 +53,16 @@ class BasicParserTest(util.ParserTest): mock_match = mock.Mock(return_value=["something"]) self.parser.aug.match = mock_match # pylint: disable=protected-access - self.assertEqual(self.parser.check_aug_version(), - ["something"]) + assert self.parser.check_aug_version() == \ + ["something"] self.parser.aug.match.side_effect = RuntimeError - self.assertIs(self.parser.check_aug_version(), False) + assert self.parser.check_aug_version() is False def test_find_config_root_no_root(self): # pylint: disable=protected-access os.remove(self.parser.loc["root"]) - self.assertRaises( - errors.NoInstallationError, self.parser._find_config_root) + with pytest.raises(errors.NoInstallationError): + self.parser._find_config_root() def test_parse_file(self): """Test parse_file. @@ -78,26 +80,26 @@ class BasicParserTest(util.ParserTest): matches = self.parser.aug.match( "/augeas/load/Httpd/incl [. ='%s']" % file_path) - self.assertTrue(matches) + assert matches def test_find_dir(self): test = self.parser.find_dir("Listen", "80") # This will only look in enabled hosts test2 = self.parser.find_dir("documentroot") - self.assertEqual(len(test), 1) - self.assertEqual(len(test2), 8) + assert len(test) == 1 + assert len(test2) == 8 def test_add_dir(self): aug_default = "/files" + self.parser.loc["default"] self.parser.add_dir(aug_default, "AddDirective", "test") - self.assertTrue(self.parser.find_dir("AddDirective", "test", aug_default)) + assert self.parser.find_dir("AddDirective", "test", aug_default) self.parser.add_dir(aug_default, "AddList", ["1", "2", "3", "4"]) matches = self.parser.find_dir("AddList", None, aug_default) for i, match in enumerate(matches): - self.assertEqual(self.parser.aug.get(match), str(i + 1)) + assert self.parser.aug.get(match) == str(i + 1) def test_add_dir_beginning(self): aug_default = "/files" + self.parser.loc["default"] @@ -105,24 +107,22 @@ class BasicParserTest(util.ParserTest): "AddDirectiveBeginning", "testBegin") - self.assertTrue(self.parser.find_dir("AddDirectiveBeginning", "testBegin", aug_default)) + assert self.parser.find_dir("AddDirectiveBeginning", "testBegin", aug_default) - self.assertEqual(self.parser.aug.get(aug_default+"/directive[1]"), "AddDirectiveBeginning") + assert self.parser.aug.get(aug_default+"/directive[1]") == "AddDirectiveBeginning" self.parser.add_dir_beginning(aug_default, "AddList", ["1", "2", "3", "4"]) matches = self.parser.find_dir("AddList", None, aug_default) for i, match in enumerate(matches): - self.assertEqual(self.parser.aug.get(match), str(i + 1)) + assert self.parser.aug.get(match) == str(i + 1) for name in ("empty.conf", "no-directives.conf"): conf = "/files" + os.path.join(self.parser.root, "sites-available", name) self.parser.add_dir_beginning(conf, "AddDirectiveBeginning", "testBegin") - self.assertGreater( - len(self.parser.find_dir("AddDirectiveBeginning", "testBegin", conf)), + assert len(self.parser.find_dir("AddDirectiveBeginning", "testBegin", conf)) > \ 0 - ) def test_empty_arg(self): - self.assertIsNone(self.parser.get_arg("/files/whatever/nonexistent")) + assert self.parser.get_arg("/files/whatever/nonexistent") is None def test_add_dir_to_ifmodssl(self): """test add_dir_to_ifmodssl. @@ -141,8 +141,8 @@ class BasicParserTest(util.ParserTest): matches = self.parser.find_dir("FakeDirective", "123") - self.assertEqual(len(matches), 1) - self.assertIn("IfModule", matches[0]) + assert len(matches) == 1 + assert "IfModule" in matches[0] def test_add_dir_to_ifmodssl_multiple(self): from certbot_apache._internal.parser import get_aug_path @@ -156,12 +156,12 @@ class BasicParserTest(util.ParserTest): matches = self.parser.find_dir("FakeDirective") - self.assertEqual(len(matches), 3) - self.assertIn("IfModule", matches[0]) + assert len(matches) == 3 + assert "IfModule" in matches[0] def test_get_aug_path(self): from certbot_apache._internal.parser import get_aug_path - self.assertEqual("/files/etc/apache", get_aug_path("/etc/apache")) + assert "/files/etc/apache" == get_aug_path("/etc/apache") def test_set_locations(self): with mock.patch("certbot_apache._internal.parser.os.path") as mock_path: @@ -171,8 +171,8 @@ class BasicParserTest(util.ParserTest): # pylint: disable=protected-access results = self.parser._set_locations() - self.assertEqual(results["default"], results["listen"]) - self.assertEqual(results["default"], results["name"]) + assert results["default"] == results["listen"] + assert results["default"] == results["name"] @mock.patch("certbot_apache._internal.parser.ApacheParser.find_dir") @mock.patch("certbot_apache._internal.parser.ApacheParser.get_arg") @@ -182,7 +182,7 @@ class BasicParserTest(util.ParserTest): with mock.patch("certbot_apache._internal.parser.logger") as mock_logger: self.parser.parse_modules() # Make sure that we got None return value and logged the file - self.assertIs(mock_logger.debug.called, True) + assert mock_logger.debug.called is True @mock.patch("certbot_apache._internal.parser.ApacheParser.find_dir") @mock.patch("certbot_apache._internal.apache_util._get_runtime_cfg") @@ -289,11 +289,11 @@ class BasicParserTest(util.ParserTest): with mock.patch( "certbot_apache._internal.parser.ApacheParser.parse_file") as mock_parse: self.parser.update_runtime_variables() - self.assertEqual(self.parser.variables, expected_vars) - self.assertEqual(len(self.parser.modules), 58) + assert self.parser.variables == expected_vars + assert len(self.parser.modules) == 58 # None of the includes in inc_val should be in parsed paths. # Make sure we tried to include them all. - self.assertEqual(mock_parse.call_count, 25) + assert mock_parse.call_count == 25 @mock.patch("certbot_apache._internal.parser.ApacheParser.find_dir") @mock.patch("certbot_apache._internal.apache_util._get_runtime_cfg") @@ -313,17 +313,16 @@ class BasicParserTest(util.ParserTest): "certbot_apache._internal.parser.ApacheParser.parse_file") as mock_parse: self.parser.update_runtime_variables() # No matching modules should have been found - self.assertEqual(len(self.parser.modules), 0) + assert len(self.parser.modules) == 0 # Only one of the three includes do not exist in already parsed # path derived from root configuration Include statements - self.assertEqual(mock_parse.call_count, 1) + assert mock_parse.call_count == 1 @mock.patch("certbot_apache._internal.apache_util.subprocess.run") def test_update_runtime_vars_bad_ctl(self, mock_run): mock_run.side_effect = OSError - self.assertRaises( - errors.MisconfigurationError, - self.parser.update_runtime_variables) + with pytest.raises(errors.MisconfigurationError): + self.parser.update_runtime_variables() @mock.patch("certbot_apache._internal.apache_util.subprocess.run") def test_update_runtime_vars_bad_exit(self, mock_run): @@ -331,16 +330,15 @@ class BasicParserTest(util.ParserTest): mock_proc.stdout = "" mock_proc.stderr = "" mock_proc.returncode = -1 - self.assertRaises( - errors.MisconfigurationError, - self.parser.update_runtime_variables) + with pytest.raises(errors.MisconfigurationError): + self.parser.update_runtime_variables() def test_add_comment(self): from certbot_apache._internal.parser import get_aug_path self.parser.add_comment(get_aug_path(self.parser.loc["name"]), "123456") comm = self.parser.find_comments("123456") - self.assertEqual(len(comm), 1) - self.assertIn(self.parser.loc["name"], comm[0]) + assert len(comm) == 1 + assert self.parser.loc["name"] in comm[0] class ParserInitTest(util.ApacheTest): @@ -357,18 +355,16 @@ class ParserInitTest(util.ApacheTest): from certbot_apache._internal.parser import ApacheParser mock_init_augeas.side_effect = errors.NoInstallationError self.config.config_test = mock.Mock() - self.assertRaises( - errors.NoInstallationError, ApacheParser, - os.path.relpath(self.config_path), self.config, + with pytest.raises(errors.NoInstallationError): + ApacheParser(os.path.relpath(self.config_path), self.config, "/dummy/vhostpath", version=(2, 4, 22)) def test_init_old_aug(self): from certbot_apache._internal.parser import ApacheParser with mock.patch("certbot_apache._internal.parser.ApacheParser.check_aug_version") as mock_c: mock_c.return_value = False - self.assertRaises( - errors.NotSupportedError, - ApacheParser, os.path.relpath(self.config_path), self.config, + with pytest.raises(errors.NotSupportedError): + ApacheParser(os.path.relpath(self.config_path), self.config, "/dummy/vhostpath", version=(2, 4, 22)) def test_root_normalized(self): @@ -382,7 +378,7 @@ class ParserInitTest(util.ApacheTest): parser = ApacheParser(path, self.config, "/dummy/vhostpath") - self.assertEqual(parser.root, self.config_path) + assert parser.root == self.config_path def test_root_absolute(self): from certbot_apache._internal.parser import ApacheParser @@ -391,7 +387,7 @@ class ParserInitTest(util.ApacheTest): parser = ApacheParser( os.path.relpath(self.config_path), self.config, "/dummy/vhostpath") - self.assertEqual(parser.root, self.config_path) + assert parser.root == self.config_path def test_root_no_trailing_slash(self): from certbot_apache._internal.parser import ApacheParser @@ -399,7 +395,7 @@ class ParserInitTest(util.ApacheTest): "update_runtime_variables"): parser = ApacheParser( self.config_path + os.path.sep, self.config, "/dummy/vhostpath") - self.assertEqual(parser.root, self.config_path) + assert parser.root == self.config_path if __name__ == "__main__": diff --git a/certbot-apache/tests/parsernode_configurator_test.py b/certbot-apache/tests/parsernode_configurator_test.py index ea704c3a9..b9f74dfbb 100644 --- a/certbot-apache/tests/parsernode_configurator_test.py +++ b/certbot-apache/tests/parsernode_configurator_test.py @@ -31,14 +31,14 @@ class ConfiguratorParserNodeTest(util.ApacheTest): # pylint: disable=too-many-p self.config.USE_PARSERNODE = True vhosts = self.config.get_virtual_hosts() # Legacy get_virtual_hosts() do not set the node - self.assertIsNotNone(vhosts[0].node) + assert vhosts[0].node is not None def test_parsernode_get_vhosts_mismatch(self): vhosts = self.config.get_virtual_hosts_v2() # One of the returned VirtualHost objects differs vhosts[0].name = "IdidntExpectThat" self.config.get_virtual_hosts_v2 = mock.MagicMock(return_value=vhosts) - with self.assertRaises(AssertionError): + with pytest.raises(AssertionError): _ = self.config.get_virtual_hosts() diff --git a/certbot-apache/tests/parsernode_util_test.py b/certbot-apache/tests/parsernode_util_test.py index fd2e35ab5..1ccc2495c 100644 --- a/certbot-apache/tests/parsernode_util_test.py +++ b/certbot-apache/tests/parsernode_util_test.py @@ -37,25 +37,28 @@ class ParserNodeUtilTest(unittest.TestCase): def test_unknown_parameter(self): params = self._setup_parsernode() params["unknown"] = "unknown" - self.assertRaises(TypeError, util.parsernode_kwargs, params) + with pytest.raises(TypeError): + util.parsernode_kwargs(params) params = self._setup_commentnode() params["unknown"] = "unknown" - self.assertRaises(TypeError, util.commentnode_kwargs, params) + with pytest.raises(TypeError): + util.commentnode_kwargs(params) params = self._setup_directivenode() params["unknown"] = "unknown" - self.assertRaises(TypeError, util.directivenode_kwargs, params) + with pytest.raises(TypeError): + util.directivenode_kwargs(params) def test_parsernode(self): params = self._setup_parsernode() ctrl = self._setup_parsernode() ancestor, dirty, filepath, metadata = util.parsernode_kwargs(params) - self.assertEqual(ancestor, ctrl["ancestor"]) - self.assertEqual(dirty, ctrl["dirty"]) - self.assertEqual(filepath, ctrl["filepath"]) - self.assertEqual(metadata, {}) + assert ancestor == ctrl["ancestor"] + assert dirty == ctrl["dirty"] + assert filepath == ctrl["filepath"] + assert metadata == {} def test_parsernode_from_metadata(self): params = self._setup_parsernode() @@ -65,14 +68,14 @@ class ParserNodeUtilTest(unittest.TestCase): # Just testing that error from missing required parameters is not raised _, _, _, metadata = util.parsernode_kwargs(params) - self.assertEqual(metadata, md) + assert metadata == md def test_commentnode(self): params = self._setup_commentnode() ctrl = self._setup_commentnode() comment, _ = util.commentnode_kwargs(params) - self.assertEqual(comment, ctrl["comment"]) + assert comment == ctrl["comment"] def test_commentnode_from_metadata(self): params = self._setup_commentnode() @@ -87,9 +90,9 @@ class ParserNodeUtilTest(unittest.TestCase): ctrl = self._setup_directivenode() name, parameters, enabled, _ = util.directivenode_kwargs(params) - self.assertEqual(name, ctrl["name"]) - self.assertEqual(parameters, ctrl["parameters"]) - self.assertEqual(enabled, ctrl["enabled"]) + assert name == ctrl["name"] + assert parameters == ctrl["parameters"] + assert enabled == ctrl["enabled"] def test_directivenode_from_metadata(self): params = self._setup_directivenode() @@ -103,15 +106,18 @@ class ParserNodeUtilTest(unittest.TestCase): def test_missing_required(self): c_params = self._setup_commentnode() c_params.pop("comment") - self.assertRaises(TypeError, util.commentnode_kwargs, c_params) + with pytest.raises(TypeError): + util.commentnode_kwargs(c_params) d_params = self._setup_directivenode() d_params.pop("ancestor") - self.assertRaises(TypeError, util.directivenode_kwargs, d_params) + with pytest.raises(TypeError): + util.directivenode_kwargs(d_params) p_params = self._setup_parsernode() p_params.pop("filepath") - self.assertRaises(TypeError, util.parsernode_kwargs, p_params) + with pytest.raises(TypeError): + util.parsernode_kwargs(p_params) if __name__ == "__main__": diff --git a/certbot-dns-cloudflare/tests/dns_cloudflare_test.py b/certbot-dns-cloudflare/tests/dns_cloudflare_test.py index 40f3ca2c0..83441a36c 100644 --- a/certbot-dns-cloudflare/tests/dns_cloudflare_test.py +++ b/certbot-dns-cloudflare/tests/dns_cloudflare_test.py @@ -45,7 +45,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic self.auth.perform([self.achall]) expected = [mock.call.add_txt_record(DOMAIN, '_acme-challenge.'+DOMAIN, mock.ANY, mock.ANY)] - self.assertEqual(expected, self.mock_client.mock_calls) + assert expected == self.mock_client.mock_calls def test_cleanup(self): # _attempt_cleanup | pylint: disable=protected-access @@ -53,7 +53,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic self.auth.cleanup([self.achall]) expected = [mock.call.del_txt_record(DOMAIN, '_acme-challenge.'+DOMAIN, mock.ANY)] - self.assertEqual(expected, self.mock_client.mock_calls) + assert expected == self.mock_client.mock_calls @test_util.patch_display_util() def test_api_token(self, unused_mock_get_utility): @@ -62,43 +62,37 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic self.auth.perform([self.achall]) expected = [mock.call.add_txt_record(DOMAIN, '_acme-challenge.'+DOMAIN, mock.ANY, mock.ANY)] - self.assertEqual(expected, self.mock_client.mock_calls) + assert expected == self.mock_client.mock_calls def test_no_creds(self): dns_test_common.write({}, self.config.cloudflare_credentials) - self.assertRaises(errors.PluginError, - self.auth.perform, - [self.achall]) + with pytest.raises(errors.PluginError): + self.auth.perform([self.achall]) def test_missing_email_or_key(self): dns_test_common.write({"cloudflare_api_key": API_KEY}, self.config.cloudflare_credentials) - self.assertRaises(errors.PluginError, - self.auth.perform, - [self.achall]) + with pytest.raises(errors.PluginError): + self.auth.perform([self.achall]) dns_test_common.write({"cloudflare_email": EMAIL}, self.config.cloudflare_credentials) - self.assertRaises(errors.PluginError, - self.auth.perform, - [self.achall]) + with pytest.raises(errors.PluginError): + self.auth.perform([self.achall]) def test_email_or_key_with_token(self): dns_test_common.write({"cloudflare_api_token": API_TOKEN, "cloudflare_email": EMAIL}, self.config.cloudflare_credentials) - self.assertRaises(errors.PluginError, - self.auth.perform, - [self.achall]) + with pytest.raises(errors.PluginError): + self.auth.perform([self.achall]) dns_test_common.write({"cloudflare_api_token": API_TOKEN, "cloudflare_api_key": API_KEY}, self.config.cloudflare_credentials) - self.assertRaises(errors.PluginError, - self.auth.perform, - [self.achall]) + with pytest.raises(errors.PluginError): + self.auth.perform([self.achall]) dns_test_common.write({"cloudflare_api_token": API_TOKEN, "cloudflare_email": EMAIL, "cloudflare_api_key": API_KEY}, self.config.cloudflare_credentials) - self.assertRaises(errors.PluginError, - self.auth.perform, - [self.achall]) + with pytest.raises(errors.PluginError): + self.auth.perform([self.achall]) class CloudflareClientTest(unittest.TestCase): @@ -126,61 +120,47 @@ class CloudflareClientTest(unittest.TestCase): post_data = self.cf.zones.dns_records.post.call_args[1]['data'] - self.assertEqual('TXT', post_data['type']) - self.assertEqual(self.record_name, post_data['name']) - self.assertEqual(self.record_content, post_data['content']) - self.assertEqual(self.record_ttl, post_data['ttl']) + assert 'TXT' == post_data['type'] + assert self.record_name == post_data['name'] + assert self.record_content == post_data['content'] + assert self.record_ttl == post_data['ttl'] def test_add_txt_record_error(self): self.cf.zones.get.return_value = [{'id': self.zone_id}] self.cf.zones.dns_records.post.side_effect = CloudFlare.exceptions.CloudFlareAPIError(1009, '', '') - self.assertRaises( - errors.PluginError, - self.cloudflare_client.add_txt_record, - DOMAIN, self.record_name, self.record_content, self.record_ttl) + with pytest.raises(errors.PluginError): + self.cloudflare_client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) def test_add_txt_record_error_during_zone_lookup(self): self.cf.zones.get.side_effect = API_ERROR - self.assertRaises( - errors.PluginError, - self.cloudflare_client.add_txt_record, - DOMAIN, self.record_name, self.record_content, self.record_ttl) + with pytest.raises(errors.PluginError): + self.cloudflare_client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) def test_add_txt_record_zone_not_found(self): self.cf.zones.get.return_value = [] - self.assertRaises( - errors.PluginError, - self.cloudflare_client.add_txt_record, - DOMAIN, self.record_name, self.record_content, self.record_ttl) + with pytest.raises(errors.PluginError): + self.cloudflare_client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) def test_add_txt_record_bad_creds(self): self.cf.zones.get.side_effect = CloudFlare.exceptions.CloudFlareAPIError(6003, '', '') - self.assertRaises( - errors.PluginError, - self.cloudflare_client.add_txt_record, - DOMAIN, self.record_name, self.record_content, self.record_ttl) + with pytest.raises(errors.PluginError): + self.cloudflare_client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) self.cf.zones.get.side_effect = CloudFlare.exceptions.CloudFlareAPIError(9103, '', '') - self.assertRaises( - errors.PluginError, - self.cloudflare_client.add_txt_record, - DOMAIN, self.record_name, self.record_content, self.record_ttl) + with pytest.raises(errors.PluginError): + self.cloudflare_client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) self.cf.zones.get.side_effect = CloudFlare.exceptions.CloudFlareAPIError(9109, '', '') - self.assertRaises( - errors.PluginError, - self.cloudflare_client.add_txt_record, - DOMAIN, self.record_name, self.record_content, self.record_ttl) + with pytest.raises(errors.PluginError): + self.cloudflare_client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) self.cf.zones.get.side_effect = CloudFlare.exceptions.CloudFlareAPIError(0, 'com.cloudflare.api.account.zone.list', '') - self.assertRaises( - errors.PluginError, - self.cloudflare_client.add_txt_record, - DOMAIN, self.record_name, self.record_content, self.record_ttl) + with pytest.raises(errors.PluginError): + self.cloudflare_client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) def test_del_txt_record(self): self.cf.zones.get.return_value = [{'id': self.zone_id}] @@ -192,13 +172,13 @@ class CloudflareClientTest(unittest.TestCase): mock.call.zones.dns_records.get(self.zone_id, params=mock.ANY), mock.call.zones.dns_records.delete(self.zone_id, self.record_id)] - self.assertEqual(expected, self.cf.mock_calls) + assert expected == self.cf.mock_calls get_data = self.cf.zones.dns_records.get.call_args[1]['params'] - self.assertEqual('TXT', get_data['type']) - self.assertEqual(self.record_name, get_data['name']) - self.assertEqual(self.record_content, get_data['content']) + assert 'TXT' == get_data['type'] + assert self.record_name == get_data['name'] + assert self.record_content == get_data['content'] def test_del_txt_record_error_during_zone_lookup(self): self.cf.zones.get.side_effect = API_ERROR @@ -215,7 +195,7 @@ class CloudflareClientTest(unittest.TestCase): mock.call.zones.dns_records.get(self.zone_id, params=mock.ANY), mock.call.zones.dns_records.delete(self.zone_id, self.record_id)] - self.assertEqual(expected, self.cf.mock_calls) + assert expected == self.cf.mock_calls def test_del_txt_record_error_during_get(self): self.cf.zones.get.return_value = [{'id': self.zone_id}] @@ -225,7 +205,7 @@ class CloudflareClientTest(unittest.TestCase): expected = [mock.call.zones.get(params=mock.ANY), mock.call.zones.dns_records.get(self.zone_id, params=mock.ANY)] - self.assertEqual(expected, self.cf.mock_calls) + assert expected == self.cf.mock_calls def test_del_txt_record_no_record(self): self.cf.zones.get.return_value = [{'id': self.zone_id}] @@ -235,7 +215,7 @@ class CloudflareClientTest(unittest.TestCase): expected = [mock.call.zones.get(params=mock.ANY), mock.call.zones.dns_records.get(self.zone_id, params=mock.ANY)] - self.assertEqual(expected, self.cf.mock_calls) + assert expected == self.cf.mock_calls def test_del_txt_record_no_zone(self): self.cf.zones.get.return_value = [{'id': None}] @@ -243,7 +223,7 @@ class CloudflareClientTest(unittest.TestCase): self.cloudflare_client.del_txt_record(DOMAIN, self.record_name, self.record_content) expected = [mock.call.zones.get(params=mock.ANY)] - self.assertEqual(expected, self.cf.mock_calls) + assert expected == self.cf.mock_calls if __name__ == "__main__": diff --git a/certbot-dns-digitalocean/tests/dns_digitalocean_test.py b/certbot-dns-digitalocean/tests/dns_digitalocean_test.py index a70768e98..ab4579b76 100644 --- a/certbot-dns-digitalocean/tests/dns_digitalocean_test.py +++ b/certbot-dns-digitalocean/tests/dns_digitalocean_test.py @@ -41,7 +41,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic self.auth.perform([self.achall]) expected = [mock.call.add_txt_record(DOMAIN, '_acme-challenge.'+DOMAIN, mock.ANY, 30)] - self.assertEqual(expected, self.mock_client.mock_calls) + assert expected == self.mock_client.mock_calls def test_cleanup(self): # _attempt_cleanup | pylint: disable=protected-access @@ -49,7 +49,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic self.auth.cleanup([self.achall]) expected = [mock.call.del_txt_record(DOMAIN, '_acme-challenge.'+DOMAIN, mock.ANY)] - self.assertEqual(expected, self.mock_client.mock_calls) + assert expected == self.mock_client.mock_calls class DigitalOceanClientTest(unittest.TestCase): @@ -90,16 +90,14 @@ class DigitalOceanClientTest(unittest.TestCase): def test_add_txt_record_fail_to_find_domain(self): self.manager.get_all_domains.return_value = [] - self.assertRaises(errors.PluginError, - self.digitalocean_client.add_txt_record, - DOMAIN, self.record_name, self.record_content, self.record_ttl) + with pytest.raises(errors.PluginError): + self.digitalocean_client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) def test_add_txt_record_error_finding_domain(self): self.manager.get_all_domains.side_effect = API_ERROR - self.assertRaises(errors.PluginError, - self.digitalocean_client.add_txt_record, - DOMAIN, self.record_name, self.record_content, self.record_ttl) + with pytest.raises(errors.PluginError): + self.digitalocean_client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) def test_add_txt_record_error_creating_record(self): domain_mock = mock.MagicMock() @@ -108,9 +106,8 @@ class DigitalOceanClientTest(unittest.TestCase): self.manager.get_all_domains.return_value = [domain_mock] - self.assertRaises(errors.PluginError, - self.digitalocean_client.add_txt_record, - DOMAIN, self.record_name, self.record_content, self.record_ttl) + with pytest.raises(errors.PluginError): + self.digitalocean_client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) def test_del_txt_record(self): first_record_mock = mock.MagicMock() @@ -138,10 +135,10 @@ class DigitalOceanClientTest(unittest.TestCase): self.digitalocean_client.del_txt_record(DOMAIN, self.record_name, self.record_content) - self.assertTrue(correct_record_mock.destroy.called) + assert correct_record_mock.destroy.called - self.assertFalse(first_record_mock.destroy.call_args_list) - self.assertFalse(last_record_mock.destroy.call_args_list) + assert not first_record_mock.destroy.call_args_list + assert not last_record_mock.destroy.call_args_list def test_del_txt_record_error_finding_domain(self): self.manager.get_all_domains.side_effect = API_ERROR diff --git a/certbot-dns-google/tests/dns_google_test.py b/certbot-dns-google/tests/dns_google_test.py index 58614d1ac..22c221714 100644 --- a/certbot-dns-google/tests/dns_google_test.py +++ b/certbot-dns-google/tests/dns_google_test.py @@ -47,7 +47,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic self.auth.perform([self.achall]) expected = [mock.call.add_txt_record(DOMAIN, '_acme-challenge.'+DOMAIN, mock.ANY, mock.ANY)] - self.assertEqual(expected, self.mock_client.mock_calls) + assert expected == self.mock_client.mock_calls def test_cleanup(self): # _attempt_cleanup | pylint: disable=protected-access @@ -55,13 +55,14 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic self.auth.cleanup([self.achall]) expected = [mock.call.del_txt_record(DOMAIN, '_acme-challenge.'+DOMAIN, mock.ANY, mock.ANY)] - self.assertEqual(expected, self.mock_client.mock_calls) + assert expected == self.mock_client.mock_calls @mock.patch('httplib2.Http.request', side_effect=ServerNotFoundError) @test_util.patch_display_util() def test_without_auth(self, unused_mock_get_utility, unused_mock): self.config.google_credentials = None - self.assertRaises(PluginError, self.auth.perform, [self.achall]) + with pytest.raises(PluginError): + self.auth.perform([self.achall]) class GoogleClientTest(unittest.TestCase): @@ -112,19 +113,17 @@ class GoogleClientTest(unittest.TestCase): unused_discovery_mock): from certbot_dns_google._internal.dns_google import _GoogleClient _GoogleClient(None) - self.assertFalse(credential_mock.called) - self.assertTrue(get_project_id_mock.called) + assert not credential_mock.called + assert get_project_id_mock.called @mock.patch('oauth2client.service_account.ServiceAccountCredentials.from_json_keyfile_name') def test_client_bad_credentials_file(self, credential_mock): credential_mock.side_effect = ValueError('Some exception buried in oauth2client') - with self.assertRaises(errors.PluginError) as cm: + with pytest.raises(errors.PluginError) as exc_info: self._setUp_client_with_mock([]) - self.assertEqual( - str(cm.exception), - "Error parsing credentials file '/not/a/real/path.json': " + assert str(exc_info.value) == \ + "Error parsing credentials file '/not/a/real/path.json': " \ "Some exception buried in oauth2client" - ) @mock.patch('oauth2client.service_account.ServiceAccountCredentials.from_json_keyfile_name') @mock.patch('certbot_dns_google._internal.dns_google.open', @@ -133,7 +132,7 @@ class GoogleClientTest(unittest.TestCase): def test_add_txt_record(self, get_project_id_mock, credential_mock): client, changes = self._setUp_client_with_mock([{'managedZones': [{'id': self.zone}]}]) credential_mock.assert_called_once_with('/not/a/real/path.json', mock.ANY) - self.assertFalse(get_project_id_mock.called) + assert not get_project_id_mock.called client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) @@ -183,10 +182,10 @@ class GoogleClientTest(unittest.TestCase): with mock.patch(mock_get_rrs) as mock_rrs: mock_rrs.return_value = {"rrdatas": ["sample-txt-contents"], "ttl": self.record_ttl} client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) - self.assertIs(changes.create.called, True) + assert changes.create.called is True deletions = changes.create.call_args_list[0][1]["body"]["deletions"][0] - self.assertIn("sample-txt-contents", deletions["rrdatas"]) - self.assertEqual(self.record_ttl, deletions["ttl"]) + assert "sample-txt-contents" in deletions["rrdatas"] + assert self.record_ttl == deletions["ttl"] @mock.patch('oauth2client.service_account.ServiceAccountCredentials.from_json_keyfile_name') @mock.patch('certbot_dns_google._internal.dns_google.open', @@ -200,10 +199,10 @@ class GoogleClientTest(unittest.TestCase): custom_ttl = 300 mock_rrs.return_value = {"rrdatas": ["sample-txt-contents"], "ttl": custom_ttl} client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) - self.assertIs(changes.create.called, True) + assert changes.create.called is True deletions = changes.create.call_args_list[0][1]["body"]["deletions"][0] - self.assertIn("sample-txt-contents", deletions["rrdatas"]) - self.assertEqual(custom_ttl, deletions["ttl"]) #otherwise HTTP 412 + assert "sample-txt-contents" in deletions["rrdatas"] + assert custom_ttl == deletions["ttl"] #otherwise HTTP 412 @mock.patch('oauth2client.service_account.ServiceAccountCredentials.from_json_keyfile_name') @mock.patch('certbot_dns_google._internal.dns_google.open', @@ -213,7 +212,7 @@ class GoogleClientTest(unittest.TestCase): [{'managedZones': [{'id': self.zone}]}]) client.add_txt_record(DOMAIN, "_acme-challenge.example.org", "example-txt-contents", self.record_ttl) - self.assertIs(changes.create.called, False) + assert changes.create.called is False @mock.patch('oauth2client.service_account.ServiceAccountCredentials.from_json_keyfile_name') @mock.patch('certbot_dns_google._internal.dns_google.open', @@ -221,8 +220,8 @@ class GoogleClientTest(unittest.TestCase): def test_add_txt_record_error_during_zone_lookup(self, unused_credential_mock): client, unused_changes = self._setUp_client_with_mock(API_ERROR) - self.assertRaises(errors.PluginError, client.add_txt_record, - DOMAIN, self.record_name, self.record_content, self.record_ttl) + with pytest.raises(errors.PluginError): + client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) @mock.patch('oauth2client.service_account.ServiceAccountCredentials.from_json_keyfile_name') @mock.patch('certbot_dns_google._internal.dns_google.open', @@ -231,8 +230,8 @@ class GoogleClientTest(unittest.TestCase): client, unused_changes = self._setUp_client_with_mock([{'managedZones': []}, {'managedZones': []}]) - self.assertRaises(errors.PluginError, client.add_txt_record, - DOMAIN, self.record_name, self.record_content, self.record_ttl) + with pytest.raises(errors.PluginError): + client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) @mock.patch('oauth2client.service_account.ServiceAccountCredentials.from_json_keyfile_name') @mock.patch('certbot_dns_google._internal.dns_google.open', @@ -241,8 +240,8 @@ class GoogleClientTest(unittest.TestCase): client, changes = self._setUp_client_with_mock([{'managedZones': [{'id': self.zone}]}]) changes.create.side_effect = API_ERROR - self.assertRaises(errors.PluginError, client.add_txt_record, - DOMAIN, self.record_name, self.record_content, self.record_ttl) + with pytest.raises(errors.PluginError): + client.add_txt_record(DOMAIN, self.record_name, self.record_content, self.record_ttl) @mock.patch('oauth2client.service_account.ServiceAccountCredentials.from_json_keyfile_name') @mock.patch('certbot_dns_google._internal.dns_google.open', @@ -346,8 +345,8 @@ class GoogleClientTest(unittest.TestCase): [{'managedZones': [{'id': self.zone}]}]) # Record name mocked in setUp found = client.get_existing_txt_rrset(self.zone, "_acme-challenge.example.org") - self.assertEqual(found["rrdatas"], ["\"example-txt-contents\""]) - self.assertEqual(found["ttl"], 60) + assert found["rrdatas"] == ["\"example-txt-contents\""] + assert found["ttl"] == 60 @mock.patch('oauth2client.service_account.ServiceAccountCredentials.from_json_keyfile_name') @mock.patch('certbot_dns_google._internal.dns_google.open', @@ -356,7 +355,7 @@ class GoogleClientTest(unittest.TestCase): client, unused_changes = self._setUp_client_with_mock( [{'managedZones': [{'id': self.zone}]}]) not_found = client.get_existing_txt_rrset(self.zone, "nonexistent.tld") - self.assertIsNone(not_found) + assert not_found is None @mock.patch('oauth2client.service_account.ServiceAccountCredentials.from_json_keyfile_name') @mock.patch('certbot_dns_google._internal.dns_google.open', @@ -366,7 +365,7 @@ class GoogleClientTest(unittest.TestCase): [{'managedZones': [{'id': self.zone}]}], API_ERROR) # Record name mocked in setUp found = client.get_existing_txt_rrset(self.zone, "_acme-challenge.example.org") - self.assertIsNone(found) + assert found is None @mock.patch('oauth2client.service_account.ServiceAccountCredentials.from_json_keyfile_name') @mock.patch('certbot_dns_google._internal.dns_google.open', @@ -375,7 +374,7 @@ class GoogleClientTest(unittest.TestCase): client, unused_changes = self._setUp_client_with_mock( [{'managedZones': [{'id': self.zone}]}], API_ERROR) rrset = client.get_existing_txt_rrset(self.zone, "_acme-challenge.example.org") - self.assertFalse(rrset) + assert not rrset def test_get_project_id(self): from certbot_dns_google._internal.dns_google import _GoogleClient @@ -385,21 +384,23 @@ class GoogleClientTest(unittest.TestCase): with mock.patch('httplib2.Http.request', return_value=(response, 'test-test-1')): project_id = _GoogleClient.get_project_id() - self.assertEqual(project_id, 'test-test-1') + assert project_id == 'test-test-1' with mock.patch('httplib2.Http.request', return_value=(response, b'test-test-1')): project_id = _GoogleClient.get_project_id() - self.assertEqual(project_id, 'test-test-1') + assert project_id == 'test-test-1' failed_response = DummyResponse() failed_response.status = 404 with mock.patch('httplib2.Http.request', return_value=(failed_response, "some detailed http error response")): - self.assertRaises(ValueError, _GoogleClient.get_project_id) + with pytest.raises(ValueError): + _GoogleClient.get_project_id() with mock.patch('httplib2.Http.request', side_effect=ServerNotFoundError): - self.assertRaises(ServerNotFoundError, _GoogleClient.get_project_id) + with pytest.raises(ServerNotFoundError): + _GoogleClient.get_project_id() class DummyResponse: diff --git a/certbot-dns-linode/tests/dns_linode_test.py b/certbot-dns-linode/tests/dns_linode_test.py index be5a7b50b..28e3f5265 100644 --- a/certbot-dns-linode/tests/dns_linode_test.py +++ b/certbot-dns-linode/tests/dns_linode_test.py @@ -46,7 +46,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, auth = Authenticator(config, "linode") auth._setup_credentials() client = auth._get_linode_client() - self.assertEqual(3, client.api_version) + assert 3 == client.api_version # pylint: disable=protected-access def test_api_version_4_detection(self): @@ -58,7 +58,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, auth = Authenticator(config, "linode") auth._setup_credentials() client = auth._get_linode_client() - self.assertEqual(4, client.api_version) + assert 4 == client.api_version # pylint: disable=protected-access def test_api_version_3_detection_empty_version(self): @@ -70,7 +70,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, auth = Authenticator(config, "linode") auth._setup_credentials() client = auth._get_linode_client() - self.assertEqual(3, client.api_version) + assert 3 == client.api_version # pylint: disable=protected-access def test_api_version_4_detection_empty_version(self): @@ -82,7 +82,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, auth = Authenticator(config, "linode") auth._setup_credentials() client = auth._get_linode_client() - self.assertEqual(4, client.api_version) + assert 4 == client.api_version # pylint: disable=protected-access def test_api_version_3_manual(self): @@ -94,7 +94,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, auth = Authenticator(config, "linode") auth._setup_credentials() client = auth._get_linode_client() - self.assertEqual(3, client.api_version) + assert 3 == client.api_version # pylint: disable=protected-access def test_api_version_4_manual(self): @@ -106,7 +106,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, auth = Authenticator(config, "linode") auth._setup_credentials() client = auth._get_linode_client() - self.assertEqual(4, client.api_version) + assert 4 == client.api_version # pylint: disable=protected-access def test_api_version_error(self): @@ -117,7 +117,8 @@ class AuthenticatorTest(test_util.TempDirTestCase, linode_propagation_seconds=0) auth = Authenticator(config, "linode") auth._setup_credentials() - self.assertRaises(errors.PluginError, auth._get_linode_client) + with pytest.raises(errors.PluginError): + auth._get_linode_client() class LinodeLexiconClientTest(unittest.TestCase, dns_test_common_lexicon.BaseLexiconClientTest): diff --git a/certbot-dns-rfc2136/tests/dns_rfc2136_test.py b/certbot-dns-rfc2136/tests/dns_rfc2136_test.py index 19943d680..3a82f1b65 100644 --- a/certbot-dns-rfc2136/tests/dns_rfc2136_test.py +++ b/certbot-dns-rfc2136/tests/dns_rfc2136_test.py @@ -47,7 +47,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic self.auth.perform([self.achall]) expected = [mock.call.add_txt_record('_acme-challenge.'+DOMAIN, mock.ANY, mock.ANY)] - self.assertEqual(expected, self.mock_client.mock_calls) + assert expected == self.mock_client.mock_calls def test_cleanup(self): # _attempt_cleanup | pylint: disable=protected-access @@ -55,16 +55,15 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic self.auth.cleanup([self.achall]) expected = [mock.call.del_txt_record('_acme-challenge.'+DOMAIN, mock.ANY)] - self.assertEqual(expected, self.mock_client.mock_calls) + assert expected == self.mock_client.mock_calls def test_invalid_algorithm_raises(self): config = VALID_CONFIG.copy() config["rfc2136_algorithm"] = "INVALID" dns_test_common.write(config, self.config.rfc2136_credentials) - self.assertRaises(errors.PluginError, - self.auth.perform, - [self.achall]) + with pytest.raises(errors.PluginError): + self.auth.perform([self.achall]) @test_util.patch_display_util() def test_valid_algorithm_passes(self, unused_mock_get_utility): @@ -79,9 +78,8 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic config["rfc2136_server"] = "example.com" dns_test_common.write(config, self.config.rfc2136_credentials) - self.assertRaises(errors.PluginError, - self.auth.perform, - [self.achall]) + with pytest.raises(errors.PluginError): + self.auth.perform([self.achall]) @test_util.patch_display_util() def test_valid_server_passes(self, unused_mock_get_utility): @@ -113,7 +111,7 @@ class RFC2136ClientTest(unittest.TestCase): self.rfc2136_client.add_txt_record("bar", "baz", 42) query_mock.assert_called_with(mock.ANY, SERVER, TIMEOUT, PORT) - self.assertIn('bar. 42 IN TXT "baz"', str(query_mock.call_args[0][0])) + assert 'bar. 42 IN TXT "baz"' in str(query_mock.call_args[0][0]) @mock.patch("dns.query.tcp") def test_add_txt_record_wraps_errors(self, query_mock): @@ -121,10 +119,8 @@ class RFC2136ClientTest(unittest.TestCase): # _find_domain | pylint: disable=protected-access self.rfc2136_client._find_domain = mock.MagicMock(return_value="example.com") - self.assertRaises( - errors.PluginError, - self.rfc2136_client.add_txt_record, - "bar", "baz", 42) + with pytest.raises(errors.PluginError): + self.rfc2136_client.add_txt_record("bar", "baz", 42) @mock.patch("dns.query.tcp") def test_add_txt_record_server_error(self, query_mock): @@ -132,10 +128,8 @@ class RFC2136ClientTest(unittest.TestCase): # _find_domain | pylint: disable=protected-access self.rfc2136_client._find_domain = mock.MagicMock(return_value="example.com") - self.assertRaises( - errors.PluginError, - self.rfc2136_client.add_txt_record, - "bar", "baz", 42) + with pytest.raises(errors.PluginError): + self.rfc2136_client.add_txt_record("bar", "baz", 42) @mock.patch("dns.query.tcp") def test_del_txt_record(self, query_mock): @@ -146,7 +140,7 @@ class RFC2136ClientTest(unittest.TestCase): self.rfc2136_client.del_txt_record("bar", "baz") query_mock.assert_called_with(mock.ANY, SERVER, TIMEOUT, PORT) - self.assertIn('bar. 0 NONE TXT "baz"', str(query_mock.call_args[0][0])) + assert 'bar. 0 NONE TXT "baz"' in str(query_mock.call_args[0][0]) @mock.patch("dns.query.tcp") def test_del_txt_record_wraps_errors(self, query_mock): @@ -154,10 +148,8 @@ class RFC2136ClientTest(unittest.TestCase): # _find_domain | pylint: disable=protected-access self.rfc2136_client._find_domain = mock.MagicMock(return_value="example.com") - self.assertRaises( - errors.PluginError, - self.rfc2136_client.del_txt_record, - "bar", "baz") + with pytest.raises(errors.PluginError): + self.rfc2136_client.del_txt_record("bar", "baz") @mock.patch("dns.query.tcp") def test_del_txt_record_server_error(self, query_mock): @@ -165,10 +157,8 @@ class RFC2136ClientTest(unittest.TestCase): # _find_domain | pylint: disable=protected-access self.rfc2136_client._find_domain = mock.MagicMock(return_value="example.com") - self.assertRaises( - errors.PluginError, - self.rfc2136_client.del_txt_record, - "bar", "baz") + with pytest.raises(errors.PluginError): + self.rfc2136_client.del_txt_record("bar", "baz") def test_find_domain(self): # _query_soa | pylint: disable=protected-access @@ -177,17 +167,14 @@ class RFC2136ClientTest(unittest.TestCase): # _find_domain | pylint: disable=protected-access domain = self.rfc2136_client._find_domain('foo.bar.'+DOMAIN) - self.assertEqual(domain, DOMAIN) + assert domain == DOMAIN def test_find_domain_wraps_errors(self): # _query_soa | pylint: disable=protected-access self.rfc2136_client._query_soa = mock.MagicMock(return_value=False) - self.assertRaises( - errors.PluginError, - # _find_domain | pylint: disable=protected-access - self.rfc2136_client._find_domain, - 'foo.bar.'+DOMAIN) + with pytest.raises(errors.PluginError): + self.rfc2136_client._find_domain('foo.bar.'+DOMAIN) @mock.patch("dns.query.tcp") def test_query_soa_found(self, query_mock): @@ -198,7 +185,7 @@ class RFC2136ClientTest(unittest.TestCase): result = self.rfc2136_client._query_soa(DOMAIN) query_mock.assert_called_with(mock.ANY, SERVER, TIMEOUT, PORT) - self.assertTrue(result) + assert result @mock.patch("dns.query.tcp") def test_query_soa_not_found(self, query_mock): @@ -208,17 +195,14 @@ class RFC2136ClientTest(unittest.TestCase): result = self.rfc2136_client._query_soa(DOMAIN) query_mock.assert_called_with(mock.ANY, SERVER, TIMEOUT, PORT) - self.assertFalse(result) + assert not result @mock.patch("dns.query.tcp") def test_query_soa_wraps_errors(self, query_mock): query_mock.side_effect = Exception - self.assertRaises( - errors.PluginError, - # _query_soa | pylint: disable=protected-access - self.rfc2136_client._query_soa, - DOMAIN) + with pytest.raises(errors.PluginError): + self.rfc2136_client._query_soa(DOMAIN) @mock.patch("dns.query.udp") @mock.patch("dns.query.tcp") @@ -232,7 +216,7 @@ class RFC2136ClientTest(unittest.TestCase): tcp_mock.assert_called_with(mock.ANY, SERVER, TIMEOUT, PORT) udp_mock.assert_called_with(mock.ANY, SERVER, TIMEOUT, PORT) - self.assertTrue(result) + assert result if __name__ == "__main__": diff --git a/certbot-dns-route53/tests/dns_route53_test.py b/certbot-dns-route53/tests/dns_route53_test.py index 3aa8f2b01..6a68b0b1e 100644 --- a/certbot-dns-route53/tests/dns_route53_test.py +++ b/certbot-dns-route53/tests/dns_route53_test.py @@ -44,22 +44,20 @@ class AuthenticatorTest(unittest.TestCase, dns_test_common.BaseAuthenticatorTest self.auth._change_txt_record.assert_called_once_with("UPSERT", '_acme-challenge.' + DOMAIN, mock.ANY) - self.assertEqual(self.auth._wait_for_change.call_count, 1) + assert self.auth._wait_for_change.call_count == 1 def test_perform_no_credentials_error(self): self.auth._change_txt_record = mock.MagicMock(side_effect=NoCredentialsError) - self.assertRaises(errors.PluginError, - self.auth.perform, - [self.achall]) + with pytest.raises(errors.PluginError): + self.auth.perform([self.achall]) def test_perform_client_error(self): self.auth._change_txt_record = mock.MagicMock( side_effect=ClientError({"Error": {"Code": "foo"}}, "bar")) - self.assertRaises(errors.PluginError, - self.auth.perform, - [self.achall]) + with pytest.raises(errors.PluginError): + self.auth.perform([self.achall]) def test_cleanup(self): self.auth._attempt_cleanup = True @@ -151,7 +149,7 @@ class ClientTest(unittest.TestCase): ] result = self.client._find_zone_id_for_domain("foo.example.com") - self.assertEqual(result, "EXAMPLE") + assert result == "EXAMPLE" def test_find_zone_id_for_domain_pagination(self): self.client.r53.get_paginator = mock.MagicMock() @@ -171,15 +169,14 @@ class ClientTest(unittest.TestCase): ] result = self.client._find_zone_id_for_domain("foo.example.com") - self.assertEqual(result, "FOO") + assert result == "FOO" def test_find_zone_id_for_domain_no_results(self): self.client.r53.get_paginator = mock.MagicMock() self.client.r53.get_paginator().paginate.return_value = [] - self.assertRaises(errors.PluginError, - self.client._find_zone_id_for_domain, - "foo.example.com") + with pytest.raises(errors.PluginError): + self.client._find_zone_id_for_domain("foo.example.com") def test_find_zone_id_for_domain_no_correct_results(self): self.client.r53.get_paginator = mock.MagicMock() @@ -192,9 +189,8 @@ class ClientTest(unittest.TestCase): }, ] - self.assertRaises(errors.PluginError, - self.client._find_zone_id_for_domain, - "foo.example.com") + with pytest.raises(errors.PluginError): + self.client._find_zone_id_for_domain("foo.example.com") def test_change_txt_record(self): self.client._find_zone_id_for_domain = mock.MagicMock() @@ -204,7 +200,7 @@ class ClientTest(unittest.TestCase): self.client._change_txt_record("FOO", DOMAIN, "foo") call_count = self.client.r53.change_resource_record_sets.call_count - self.assertEqual(call_count, 1) + assert call_count == 1 def test_change_txt_record_delete(self): self.client._find_zone_id_for_domain = mock.MagicMock() @@ -218,13 +214,12 @@ class ClientTest(unittest.TestCase): self.client._change_txt_record("DELETE", DOMAIN, validation) call_count = self.client.r53.change_resource_record_sets.call_count - self.assertEqual(call_count, 1) + assert call_count == 1 call_args = self.client.r53.change_resource_record_sets.call_args_list[0][1] call_args_batch = call_args["ChangeBatch"]["Changes"][0] - self.assertEqual(call_args_batch["Action"], "DELETE") - self.assertEqual( - call_args_batch["ResourceRecordSet"]["ResourceRecords"], - [validation_record]) + assert call_args_batch["Action"] == "DELETE" + assert call_args_batch["ResourceRecordSet"]["ResourceRecords"] == \ + [validation_record] def test_change_txt_record_multirecord(self): self.client._find_zone_id_for_domain = mock.MagicMock() @@ -241,12 +236,11 @@ class ClientTest(unittest.TestCase): call_count = self.client.r53.change_resource_record_sets.call_count call_args = self.client.r53.change_resource_record_sets.call_args_list[0][1] call_args_batch = call_args["ChangeBatch"]["Changes"][0] - self.assertEqual(call_args_batch["Action"], "UPSERT") - self.assertEqual( - call_args_batch["ResourceRecordSet"]["ResourceRecords"], - [{"Value": "\"pre-existing-value-two\""}]) + assert call_args_batch["Action"] == "UPSERT" + assert call_args_batch["ResourceRecordSet"]["ResourceRecords"] == \ + [{"Value": "\"pre-existing-value-two\""}] - self.assertEqual(call_count, 1) + assert call_count == 1 def test_wait_for_change(self): self.client.r53.get_change = mock.MagicMock( @@ -255,7 +249,7 @@ class ClientTest(unittest.TestCase): self.client._wait_for_change(1) - self.assertTrue(self.client.r53.get_change.called) + assert self.client.r53.get_change.called if __name__ == "__main__": diff --git a/certbot-nginx/tests/configurator_test.py b/certbot-nginx/tests/configurator_test.py index 50e02f5c3..9698b4108 100644 --- a/certbot-nginx/tests/configurator_test.py +++ b/certbot-nginx/tests/configurator_test.py @@ -36,12 +36,12 @@ class NginxConfiguratorTest(util.NginxTest): @mock.patch("certbot_nginx._internal.configurator.util.exe_exists") def test_prepare_no_install(self, mock_exe_exists): mock_exe_exists.return_value = False - self.assertRaises( - errors.NoInstallationError, self.config.prepare) + with pytest.raises(errors.NoInstallationError): + self.config.prepare() def test_prepare(self): - self.assertEqual((1, 6, 2), self.config.version) - self.assertEqual(14, len(self.config.parser.parsed)) + assert (1, 6, 2) == self.config.version + assert 14 == len(self.config.parser.parsed) @mock.patch("certbot_nginx._internal.configurator.util.exe_exists") @mock.patch("certbot_nginx._internal.configurator.subprocess.run") @@ -60,7 +60,7 @@ class NginxConfiguratorTest(util.NginxTest): self.config.version = None self.config.config_test = mock.Mock() self.config.prepare() - self.assertEqual((1, 6, 2), self.config.version) + assert (1, 6, 2) == self.config.version def test_prepare_locked(self): server_root = self.config.conf("server-root") @@ -77,8 +77,8 @@ class NginxConfiguratorTest(util.NginxTest): self.config.prepare() except errors.PluginError as err: err_msg = str(err) - self.assertIn("lock", err_msg) - self.assertIn(self.config.conf("server-root"), err_msg) + assert "lock" in err_msg + assert self.config.conf("server-root") in err_msg else: # pragma: no cover self.fail("Exception wasn't raised!") @@ -88,23 +88,23 @@ class NginxConfiguratorTest(util.NginxTest): mock_gethostbyaddr.return_value = ('155.225.50.69.nephoscale.net', [], []) mock_gethostname.return_value = ('example.net') names = self.config.get_all_names() - self.assertEqual(names, { + assert names == { "155.225.50.69.nephoscale.net", "www.example.org", "another.alias", "migration.com", "summer.com", "geese.com", "sslon.com", "globalssl.com", "globalsslsetssl.com", "ipv6.com", "ipv6ssl.com", - "headers.com", "example.net", "ssl.both.com"}) + "headers.com", "example.net", "ssl.both.com"} def test_supported_enhancements(self): - self.assertEqual(['redirect', 'ensure-http-header', 'staple-ocsp'], - self.config.supported_enhancements()) + assert ['redirect', 'ensure-http-header', 'staple-ocsp'] == \ + self.config.supported_enhancements() def test_enhance(self): - self.assertRaises( - errors.PluginError, self.config.enhance, 'myhost', 'unknown_enhancement') + with pytest.raises(errors.PluginError): + self.config.enhance('myhost', 'unknown_enhancement') def test_get_chall_pref(self): - self.assertEqual([challenges.HTTP01], - self.config.get_chall_pref('myhost')) + assert [challenges.HTTP01] == \ + self.config.get_chall_pref('myhost') def test_save(self): filep = self.config.parser.abs_path('sites-enabled/example.com') @@ -119,14 +119,14 @@ class NginxConfiguratorTest(util.NginxTest): # pylint: disable=protected-access parsed = self.config.parser._parse_files(filep, override=True) - self.assertEqual([[['server'], + assert [[['server'], [['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', '.example.com'], ['server_name', 'example.*'], ['listen', '5001', 'ssl'], - ['#', parser.COMMENT]]]], - parsed[0]) + ['#', parser.COMMENT]]]] == \ + parsed[0] def test_choose_vhosts_alias(self): self._test_choose_vhosts_common('alias', 'server_conf') @@ -176,14 +176,13 @@ class NginxConfiguratorTest(util.NginxTest): vhost = self.config.choose_vhosts(name)[0] path = os.path.relpath(vhost.filep, self.temp_dir) - self.assertEqual(conf_names[conf], vhost.names) - self.assertEqual(conf_path[name], path) + assert conf_names[conf] == vhost.names + assert conf_path[name] == path # IPv6 specific checks if name == "ipv6.com": - self.assertTrue(vhost.ipv6_enabled()) + assert vhost.ipv6_enabled() # Make sure that we have SSL enabled also for IPv6 addr - self.assertTrue( - any(True for x in vhost.addrs if x.ssl and x.ipv6)) + assert any(True for x in vhost.addrs if x.ssl and x.ipv6) def test_choose_vhosts_bad(self): bad_results = ['www.foo.com', 'example', 't.www.bar.co', @@ -191,14 +190,14 @@ class NginxConfiguratorTest(util.NginxTest): for name in bad_results: with self.subTest(name=name): - self.assertRaises(errors.MisconfigurationError, - self.config.choose_vhosts, name) + with pytest.raises(errors.MisconfigurationError): + self.config.choose_vhosts(name) def test_ipv6only(self): # ipv6_info: (ipv6_active, ipv6only_present) - self.assertEqual((True, False), self.config.ipv6_info("80")) + assert (True, False) == self.config.ipv6_info("80") # Port 443 has ipv6only=on because of ipv6ssl.com vhost - self.assertEqual((True, True), self.config.ipv6_info("443")) + assert (True, True) == self.config.ipv6_info("443") def test_ipv6only_detection(self): self.config.version = (1, 3, 1) @@ -211,15 +210,15 @@ class NginxConfiguratorTest(util.NginxTest): "example/fullchain.pem") for addr in self.config.choose_vhosts("ipv6.com")[0].addrs: - self.assertFalse(addr.ipv6only) + assert not addr.ipv6only def test_more_info(self): - self.assertIn('nginx.conf', self.config.more_info()) + assert 'nginx.conf' in self.config.more_info() def test_deploy_cert_requires_fullchain_path(self): self.config.version = (1, 3, 1) - self.assertRaises(errors.PluginError, self.config.deploy_cert, - "www.example.com", + with pytest.raises(errors.PluginError): + self.config.deploy_cert("www.example.com", "example/cert.pem", "example/key.pem", "example/chain.pem", @@ -228,10 +227,8 @@ class NginxConfiguratorTest(util.NginxTest): @mock.patch('certbot_nginx._internal.parser.NginxParser.update_or_add_server_directives') def test_deploy_cert_raise_on_add_error(self, mock_update_or_add_server_directives): mock_update_or_add_server_directives.side_effect = errors.MisconfigurationError() - self.assertRaises( - errors.PluginError, - self.config.deploy_cert, - "migration.com", + with pytest.raises(errors.PluginError): + self.config.deploy_cert("migration.com", "example/cert.pem", "example/key.pem", "example/chain.pem", @@ -264,7 +261,7 @@ class NginxConfiguratorTest(util.NginxTest): parsed_server_conf = util.filter_comments(self.config.parser.parsed[server_conf]) parsed_nginx_conf = util.filter_comments(self.config.parser.parsed[nginx_conf]) - self.assertEqual([[['server'], + assert [[['server'], [ ['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], @@ -276,11 +273,11 @@ class NginxConfiguratorTest(util.NginxTest): ['ssl_certificate_key', 'example/key.pem'], ['include', self.config.mod_ssl_conf], ['ssl_dhparam', self.config.ssl_dhparams], - ]]], - parsed_example_conf) - self.assertEqual([['server_name', 'somename', 'alias', 'another.alias']], - parsed_server_conf) - self.assertTrue(util.contains_at_depth( + ]]] == \ + parsed_example_conf + assert [['server_name', 'somename', 'alias', 'another.alias']] == \ + parsed_server_conf + assert util.contains_at_depth( parsed_nginx_conf, [['server'], [ @@ -296,7 +293,7 @@ class NginxConfiguratorTest(util.NginxTest): ['include', self.config.mod_ssl_conf], ['ssl_dhparam', self.config.ssl_dhparams], ]], - 2)) + 2) def test_deploy_cert_add_explicit_listen(self): migration_conf = self.config.parser.abs_path('sites-enabled/migration.com') @@ -309,7 +306,7 @@ class NginxConfiguratorTest(util.NginxTest): self.config.save() self.config.parser.load() parsed_migration_conf = util.filter_comments(self.config.parser.parsed[migration_conf]) - self.assertEqual([['server'], + assert [['server'], [ ['server_name', 'migration.com'], ['server_name', 'summer.com'], @@ -320,8 +317,8 @@ class NginxConfiguratorTest(util.NginxTest): ['ssl_certificate_key', 'summer/key.pem'], ['include', self.config.mod_ssl_conf], ['ssl_dhparam', self.config.ssl_dhparams], - ]], - parsed_migration_conf[0]) + ]] == \ + parsed_migration_conf[0] @mock.patch("certbot_nginx._internal.configurator.http_01.NginxHttp01.perform") @mock.patch("certbot_nginx._internal.configurator.NginxConfigurator.restart") @@ -343,13 +340,13 @@ class NginxConfiguratorTest(util.NginxTest): mock_http_perform.return_value = expected[:] responses = self.config.perform([achall]) - self.assertEqual(mock_http_perform.call_count, 1) - self.assertEqual(responses, expected) + assert mock_http_perform.call_count == 1 + assert responses == expected self.config.cleanup([achall]) - self.assertEqual(0, self.config._chall_out) # pylint: disable=protected-access - self.assertEqual(mock_revert.call_count, 1) - self.assertEqual(mock_restart.call_count, 2) + assert 0 == self.config._chall_out # pylint: disable=protected-access + assert mock_revert.call_count == 1 + assert mock_restart.call_count == 2 @mock.patch("certbot_nginx._internal.configurator.subprocess.run") def test_get_version(self, mock_run): @@ -361,7 +358,7 @@ class NginxConfiguratorTest(util.NginxTest): "TLS SNI support enabled", "configure arguments: --prefix=/usr/local/Cellar/" "nginx/1.6.2 --with-http_ssl_module"]) - self.assertEqual(self.config.get_version(), (1, 4, 2)) + assert self.config.get_version() == (1, 4, 2) mock_run.return_value.stdout = "" mock_run.return_value.stderr = "\n".join( @@ -370,7 +367,7 @@ class NginxConfiguratorTest(util.NginxTest): " (based on LLVM 3.5svn)", "TLS SNI support enabled", "configure arguments: --with-http_ssl_module"]) - self.assertEqual(self.config.get_version(), (0, 9)) + assert self.config.get_version() == (0, 9) mock_run.return_value.stdout = "" mock_run.return_value.stderr = "\n".join( @@ -379,13 +376,15 @@ class NginxConfiguratorTest(util.NginxTest): " (based on LLVM 3.5svn)", "TLS SNI support enabled", "configure arguments: --with-http_ssl_module"]) - self.assertRaises(errors.PluginError, self.config.get_version) + with pytest.raises(errors.PluginError): + self.config.get_version() mock_run.return_value.stdout = "" mock_run.return_value.stderr = "\n".join( ["nginx version: nginx/1.4.2", "TLS SNI support enabled"]) - self.assertRaises(errors.PluginError, self.config.get_version) + with pytest.raises(errors.PluginError): + self.config.get_version() mock_run.return_value.stdout = "" mock_run.return_value.stderr = "\n".join( @@ -393,7 +392,8 @@ class NginxConfiguratorTest(util.NginxTest): "built by clang 6.0 (clang-600.0.56)" " (based on LLVM 3.5svn)", "configure arguments: --with-http_ssl_module"]) - self.assertRaises(errors.PluginError, self.config.get_version) + with pytest.raises(errors.PluginError): + self.config.get_version() mock_run.return_value.stdout = "" mock_run.return_value.stderr = "\n".join( @@ -402,10 +402,12 @@ class NginxConfiguratorTest(util.NginxTest): " (based on LLVM 3.5svn)", "TLS SNI support enabled", "configure arguments: --with-http_ssl_module"]) - self.assertRaises(errors.NotSupportedError, self.config.get_version) + with pytest.raises(errors.NotSupportedError): + self.config.get_version() mock_run.side_effect = OSError("Can't find program") - self.assertRaises(errors.PluginError, self.config.get_version) + with pytest.raises(errors.PluginError): + self.config.get_version() @mock.patch("certbot_nginx._internal.configurator.subprocess.run") def test_get_openssl_version(self, mock_run): @@ -418,7 +420,7 @@ class NginxConfiguratorTest(util.NginxTest): TLS SNI support enabled configure arguments: """ - self.assertEqual(self.config._get_openssl_version(), "1.0.2g") + assert self.config._get_openssl_version() == "1.0.2g" mock_run.return_value.stdout = "" mock_run.return_value.stderr = """ @@ -428,7 +430,7 @@ class NginxConfiguratorTest(util.NginxTest): TLS SNI support enabled configure arguments: """ - self.assertEqual(self.config._get_openssl_version(), "1.0.2-beta1") + assert self.config._get_openssl_version() == "1.0.2-beta1" mock_run.return_value.stdout = "" mock_run.return_value.stderr = """ @@ -438,7 +440,7 @@ class NginxConfiguratorTest(util.NginxTest): TLS SNI support enabled configure arguments: """ - self.assertEqual(self.config._get_openssl_version(), "1.0.2") + assert self.config._get_openssl_version() == "1.0.2" mock_run.return_value.stdout = "" mock_run.return_value.stderr = """ @@ -448,7 +450,7 @@ class NginxConfiguratorTest(util.NginxTest): TLS SNI support enabled configure arguments: """ - self.assertEqual(self.config._get_openssl_version(), "1.0.2a") + assert self.config._get_openssl_version() == "1.0.2a" mock_run.return_value.stdout = "" mock_run.return_value.stderr = """ @@ -458,7 +460,7 @@ class NginxConfiguratorTest(util.NginxTest): TLS SNI support enabled configure arguments: """ - self.assertEqual(self.config._get_openssl_version(), "") + assert self.config._get_openssl_version() == "" mock_run.return_value.stdout = "" mock_run.return_value.stderr = """ @@ -467,7 +469,7 @@ class NginxConfiguratorTest(util.NginxTest): TLS SNI support enabled configure arguments: """ - self.assertEqual(self.config._get_openssl_version(), "") + assert self.config._get_openssl_version() == "" @mock.patch("certbot_nginx._internal.configurator.subprocess.run") @mock.patch("certbot_nginx._internal.configurator.time") @@ -477,7 +479,7 @@ class NginxConfiguratorTest(util.NginxTest): mocked.stderr = '' mocked.returncode = 0 self.config.restart() - self.assertEqual(mock_run.call_count, 1) + assert mock_run.call_count == 1 mock_time.sleep.assert_called_once_with(0.1234) @mock.patch("certbot_nginx._internal.configurator.subprocess.run") @@ -487,19 +489,22 @@ class NginxConfiguratorTest(util.NginxTest): mocked.stdout = '' mocked.stderr = '' mocked.returncode = 1 - self.assertRaises(errors.MisconfigurationError, self.config.restart) - self.assertEqual(mock_run.call_count, 2) + with pytest.raises(errors.MisconfigurationError): + self.config.restart() + assert mock_run.call_count == 2 mock_log_debug.assert_called_once_with("nginx reload failed:\n%s", "") @mock.patch("certbot_nginx._internal.configurator.subprocess.run") def test_no_nginx_start(self, mock_run): mock_run.side_effect = OSError("Can't find program") - self.assertRaises(errors.MisconfigurationError, self.config.restart) + with pytest.raises(errors.MisconfigurationError): + self.config.restart() @mock.patch("certbot.util.run_script") def test_config_test_bad_process(self, mock_run_script): mock_run_script.side_effect = errors.SubprocessError - self.assertRaises(errors.MisconfigurationError, self.config.config_test) + with pytest.raises(errors.MisconfigurationError): + self.config.config_test() @mock.patch("certbot.util.run_script") def test_config_test(self, _): @@ -508,28 +513,32 @@ class NginxConfiguratorTest(util.NginxTest): @mock.patch("certbot.reverter.Reverter.recovery_routine") def test_recovery_routine_throws_error_from_reverter(self, mock_recovery_routine): mock_recovery_routine.side_effect = errors.ReverterError("foo") - self.assertRaises(errors.PluginError, self.config.recovery_routine) + with pytest.raises(errors.PluginError): + self.config.recovery_routine() @mock.patch("certbot.reverter.Reverter.rollback_checkpoints") def test_rollback_checkpoints_throws_error_from_reverter(self, mock_rollback_checkpoints): mock_rollback_checkpoints.side_effect = errors.ReverterError("foo") - self.assertRaises(errors.PluginError, self.config.rollback_checkpoints) + with pytest.raises(errors.PluginError): + self.config.rollback_checkpoints() @mock.patch("certbot.reverter.Reverter.revert_temporary_config") def test_revert_challenge_config_throws_error_from_reverter(self, mock_revert_temporary_config): mock_revert_temporary_config.side_effect = errors.ReverterError("foo") - self.assertRaises(errors.PluginError, self.config.revert_challenge_config) + with pytest.raises(errors.PluginError): + self.config.revert_challenge_config() @mock.patch("certbot.reverter.Reverter.add_to_checkpoint") def test_save_throws_error_from_reverter(self, mock_add_to_checkpoint): mock_add_to_checkpoint.side_effect = errors.ReverterError("foo") - self.assertRaises(errors.PluginError, self.config.save) + with pytest.raises(errors.PluginError): + self.config.save() def test_get_snakeoil_paths(self): # pylint: disable=protected-access cert, key = self.config._get_snakeoil_paths() - self.assertTrue(os.path.exists(cert)) - self.assertTrue(os.path.exists(key)) + assert os.path.exists(cert) + assert os.path.exists(key) with open(cert) as cert_file: OpenSSL.crypto.load_certificate( OpenSSL.crypto.FILETYPE_PEM, cert_file.read()) @@ -546,7 +555,7 @@ class NginxConfiguratorTest(util.NginxTest): self.config.enhance("www.example.com", "redirect") generated_conf = self.config.parser.parsed[example_conf] - self.assertIs(util.contains_at_depth(generated_conf, expected, 2), True) + assert util.contains_at_depth(generated_conf, expected, 2) is True # Test that we successfully add a redirect when there is # no listen directive @@ -556,7 +565,7 @@ class NginxConfiguratorTest(util.NginxTest): expected = UnspacedList(_redirect_block_for_domain("migration.com"))[0] generated_conf = self.config.parser.parsed[migration_conf] - self.assertIs(util.contains_at_depth(generated_conf, expected, 2), True) + assert util.contains_at_depth(generated_conf, expected, 2) is True def test_split_for_redirect(self): example_conf = self.config.parser.abs_path('sites-enabled/example.com') @@ -568,8 +577,7 @@ class NginxConfiguratorTest(util.NginxTest): "example/fullchain.pem") self.config.enhance("www.example.com", "redirect") generated_conf = self.config.parser.parsed[example_conf] - self.assertEqual( - [[['server'], [ + assert [[['server'], [ ['server_name', '.example.com'], ['server_name', 'example.*'], [], ['listen', '5001', 'ssl'], ['#', ' managed by Certbot'], @@ -586,8 +594,8 @@ class NginxConfiguratorTest(util.NginxTest): ['listen', '127.0.0.1'], ['server_name', '.example.com'], ['server_name', 'example.*'], - ['return', '404'], ['#', ' managed by Certbot'], [], [], []]]], - generated_conf) + ['return', '404'], ['#', ' managed by Certbot'], [], [], []]]] == \ + generated_conf def test_split_for_headers(self): example_conf = self.config.parser.abs_path('sites-enabled/example.com') @@ -599,8 +607,7 @@ class NginxConfiguratorTest(util.NginxTest): "example/fullchain.pem") self.config.enhance("www.example.com", "ensure-http-header", "Strict-Transport-Security") generated_conf = self.config.parser.parsed[example_conf] - self.assertEqual( - [[['server'], [ + assert [[['server'], [ ['server_name', '.example.com'], ['server_name', 'example.*'], [], ['listen', '5001', 'ssl'], ['#', ' managed by Certbot'], @@ -617,8 +624,8 @@ class NginxConfiguratorTest(util.NginxTest): ['listen', '127.0.0.1'], ['server_name', '.example.com'], ['server_name', 'example.*'], - [], [], []]]], - generated_conf) + [], [], []]]] == \ + generated_conf def test_http_header_hsts(self): example_conf = self.config.parser.abs_path('sites-enabled/example.com') @@ -626,7 +633,7 @@ class NginxConfiguratorTest(util.NginxTest): "Strict-Transport-Security") expected = ['add_header', 'Strict-Transport-Security', '"max-age=31536000"', 'always'] generated_conf = self.config.parser.parsed[example_conf] - self.assertIs(util.contains_at_depth(generated_conf, expected, 2), True) + assert util.contains_at_depth(generated_conf, expected, 2) is True def test_multiple_headers_hsts(self): headers_conf = self.config.parser.abs_path('sites-enabled/headers.com') @@ -634,14 +641,13 @@ class NginxConfiguratorTest(util.NginxTest): "Strict-Transport-Security") expected = ['add_header', 'Strict-Transport-Security', '"max-age=31536000"', 'always'] generated_conf = self.config.parser.parsed[headers_conf] - self.assertIs(util.contains_at_depth(generated_conf, expected, 2), True) + assert util.contains_at_depth(generated_conf, expected, 2) is True def test_http_header_hsts_twice(self): self.config.enhance("www.example.com", "ensure-http-header", "Strict-Transport-Security") - self.assertRaises( - errors.PluginEnhancementAlreadyPresent, - self.config.enhance, "www.example.com", + with pytest.raises(errors.PluginEnhancementAlreadyPresent): + self.config.enhance("www.example.com", "ensure-http-header", "Strict-Transport-Security") @mock.patch('certbot_nginx._internal.obj.VirtualHost.contains_list') @@ -652,15 +658,15 @@ class NginxConfiguratorTest(util.NginxTest): mock_contains_list.return_value = True with mock.patch("certbot_nginx._internal.configurator.logger") as mock_logger: self.config.enhance("www.example.com", "redirect") - self.assertEqual(mock_logger.info.call_args[0][0], - "Traffic on port %s already redirecting to ssl in %s") + assert mock_logger.info.call_args[0][0] == \ + "Traffic on port %s already redirecting to ssl in %s" def test_redirect_dont_enhance(self): # Test that we don't accidentally add redirect to ssl-only block with mock.patch("certbot_nginx._internal.configurator.logger") as mock_logger: self.config.enhance("geese.com", "redirect") - self.assertEqual(mock_logger.info.call_args[0][0], - 'No matching insecure server blocks listening on port %s found.') + assert mock_logger.info.call_args[0][0] == \ + 'No matching insecure server blocks listening on port %s found.' def test_double_redirect(self): # Test that we add one redirect for each domain @@ -672,23 +678,23 @@ class NginxConfiguratorTest(util.NginxTest): expected2 = UnspacedList(_redirect_block_for_domain("example.org"))[0] generated_conf = self.config.parser.parsed[example_conf] - self.assertTrue(util.contains_at_depth(generated_conf, expected1, 2)) - self.assertTrue(util.contains_at_depth(generated_conf, expected2, 2)) + assert util.contains_at_depth(generated_conf, expected1, 2) + assert util.contains_at_depth(generated_conf, expected2, 2) def test_staple_ocsp_bad_version(self): self.config.version = (1, 3, 1) - self.assertRaises(errors.PluginError, self.config.enhance, - "www.example.com", "staple-ocsp", "chain_path") + with pytest.raises(errors.PluginError): + self.config.enhance("www.example.com", "staple-ocsp", "chain_path") def test_staple_ocsp_no_chain_path(self): - self.assertRaises(errors.PluginError, self.config.enhance, - "www.example.com", "staple-ocsp", None) + with pytest.raises(errors.PluginError): + self.config.enhance("www.example.com", "staple-ocsp", None) def test_staple_ocsp_internal_error(self): self.config.enhance("www.example.com", "staple-ocsp", "chain_path") # error is raised because the server block has conflicting directives - self.assertRaises(errors.PluginError, self.config.enhance, - "www.example.com", "staple-ocsp", "different_path") + with pytest.raises(errors.PluginError): + self.config.enhance("www.example.com", "staple-ocsp", "different_path") def test_staple_ocsp(self): chain_path = "example/chain.pem" @@ -697,13 +703,13 @@ class NginxConfiguratorTest(util.NginxTest): example_conf = self.config.parser.abs_path('sites-enabled/example.com') generated_conf = self.config.parser.parsed[example_conf] - self.assertTrue(util.contains_at_depth( + assert util.contains_at_depth( generated_conf, - ['ssl_trusted_certificate', 'example/chain.pem'], 2)) - self.assertTrue(util.contains_at_depth( - generated_conf, ['ssl_stapling', 'on'], 2)) - self.assertTrue(util.contains_at_depth( - generated_conf, ['ssl_stapling_verify', 'on'], 2)) + ['ssl_trusted_certificate', 'example/chain.pem'], 2) + assert util.contains_at_depth( + generated_conf, ['ssl_stapling', 'on'], 2) + assert util.contains_at_depth( + generated_conf, ['ssl_stapling_verify', 'on'], 2) def test_deploy_no_match_default_set(self): default_conf = self.config.parser.abs_path('sites-enabled/default') @@ -723,7 +729,7 @@ class NginxConfiguratorTest(util.NginxTest): parsed_default_conf = util.filter_comments(self.config.parser.parsed[default_conf]) - self.assertEqual([[['server'], + assert [[['server'], [['listen', 'myhost', 'default_server'], ['listen', 'otherhost', 'default_server'], ['server_name', '"www.example.org"'], @@ -741,8 +747,8 @@ class NginxConfiguratorTest(util.NginxTest): ['ssl_certificate', 'example/fullchain.pem'], ['ssl_certificate_key', 'example/key.pem'], ['include', self.config.mod_ssl_conf], - ['ssl_dhparam', self.config.ssl_dhparams]]]], - parsed_default_conf) + ['ssl_dhparam', self.config.ssl_dhparams]]]] == \ + parsed_default_conf self.config.deploy_cert( "nomatch.com", @@ -756,7 +762,7 @@ class NginxConfiguratorTest(util.NginxTest): parsed_default_conf = util.filter_comments(self.config.parser.parsed[default_conf]) - self.assertTrue(util.contains_at_depth(parsed_default_conf, "nomatch.com", 3)) + assert util.contains_at_depth(parsed_default_conf, "nomatch.com", 3) def test_deploy_no_match_default_set_multi_level_path(self): default_conf = self.config.parser.abs_path('sites-enabled/default') @@ -777,7 +783,7 @@ class NginxConfiguratorTest(util.NginxTest): parsed_foo_conf = util.filter_comments(self.config.parser.parsed[foo_conf]) - self.assertEqual([['server'], + assert [['server'], [['listen', '*:80', 'ssl'], ['server_name', 'www.nomatch.com'], ['root', '/home/ubuntu/sites/foo/'], @@ -788,8 +794,8 @@ class NginxConfiguratorTest(util.NginxTest): [['location', '=', 'exact_match\\.php$'], []], [['location', '^~', 'ignore_regex\\.php$'], []], ['ssl_certificate', 'example/fullchain.pem'], - ['ssl_certificate_key', 'example/key.pem']]], - parsed_foo_conf[1][1][1]) + ['ssl_certificate_key', 'example/key.pem']]] == \ + parsed_foo_conf[1][1][1] def test_deploy_no_match_no_default_set(self): default_conf = self.config.parser.abs_path('sites-enabled/default') @@ -799,14 +805,14 @@ class NginxConfiguratorTest(util.NginxTest): del self.config.parser.parsed[foo_conf][2][1][0][1][0] self.config.version = (1, 3, 1) - self.assertRaises(errors.MisconfigurationError, self.config.deploy_cert, - "www.nomatch.com", "example/cert.pem", "example/key.pem", + with pytest.raises(errors.MisconfigurationError): + self.config.deploy_cert("www.nomatch.com", "example/cert.pem", "example/key.pem", "example/chain.pem", "example/fullchain.pem") def test_deploy_no_match_fail_multiple_defaults(self): self.config.version = (1, 3, 1) - self.assertRaises(errors.MisconfigurationError, self.config.deploy_cert, - "www.nomatch.com", "example/cert.pem", "example/key.pem", + with pytest.raises(errors.MisconfigurationError): + self.config.deploy_cert("www.nomatch.com", "example/cert.pem", "example/key.pem", "example/chain.pem", "example/fullchain.pem") def test_deploy_no_match_multiple_defaults_ok(self): @@ -845,7 +851,7 @@ class NginxConfiguratorTest(util.NginxTest): expected = UnspacedList(_redirect_block_for_domain("www.nomatch.com"))[0] generated_conf = self.config.parser.parsed[default_conf] - self.assertTrue(util.contains_at_depth(generated_conf, expected, 2)) + assert util.contains_at_depth(generated_conf, expected, 2) @mock.patch('certbot.reverter.logger') @mock.patch('certbot_nginx._internal.parser.NginxParser.load') @@ -853,7 +859,7 @@ class NginxConfiguratorTest(util.NginxTest): self.config.recovery_routine() self.config.revert_challenge_config() self.config.rollback_checkpoints() - self.assertEqual(mock_parser_load.call_count, 3) + assert mock_parser_load.call_count == 3 def test_choose_vhosts_wildcard(self): # pylint: disable=protected-access @@ -865,11 +871,11 @@ class NginxConfiguratorTest(util.NginxTest): vhs = self.config._choose_vhosts_wildcard("*.com", prefer_ssl=True) # Check that the dialog was called with migration.com - self.assertIn(vhost, mock_select_vhs.call_args[0][0]) + assert vhost in mock_select_vhs.call_args[0][0] # And the actual returned values - self.assertEqual(len(vhs), 1) - self.assertEqual(vhs[0], vhost) + assert len(vhs) == 1 + assert vhs[0] == vhost def test_choose_vhosts_wildcard_redirect(self): # pylint: disable=protected-access @@ -881,11 +887,11 @@ class NginxConfiguratorTest(util.NginxTest): vhs = self.config._choose_vhosts_wildcard("*.com", prefer_ssl=False) # Check that the dialog was called with migration.com - self.assertIn(vhost, mock_select_vhs.call_args[0][0]) + assert vhost in mock_select_vhs.call_args[0][0] # And the actual returned values - self.assertEqual(len(vhs), 1) - self.assertEqual(vhs[0], vhost) + assert len(vhs) == 1 + assert vhs[0] == vhost def test_deploy_cert_wildcard(self): # pylint: disable=protected-access @@ -898,17 +904,16 @@ class NginxConfiguratorTest(util.NginxTest): with mock.patch(mock_d) as mock_dep: self.config.deploy_cert("*.com", "/tmp/path", "/tmp/path", "/tmp/path", "/tmp/path") - self.assertTrue(mock_dep.called) - self.assertEqual(len(mock_dep.call_args_list), 1) - self.assertEqual(vhost, mock_dep.call_args_list[0][0][0]) + assert mock_dep.called + assert len(mock_dep.call_args_list) == 1 + assert vhost == mock_dep.call_args_list[0][0][0] @mock.patch("certbot_nginx._internal.display_ops.select_vhost_multiple") def test_deploy_cert_wildcard_no_vhosts(self, mock_dialog): # pylint: disable=protected-access mock_dialog.return_value = [] - self.assertRaises(errors.PluginError, - self.config.deploy_cert, - "*.wild.cat", "/tmp/path", "/tmp/path", + with pytest.raises(errors.PluginError): + self.config.deploy_cert("*.wild.cat", "/tmp/path", "/tmp/path", "/tmp/path", "/tmp/path") @mock.patch("certbot_nginx._internal.display_ops.select_vhost_multiple") @@ -918,7 +923,7 @@ class NginxConfiguratorTest(util.NginxTest): if 'geese.com' in x.names][0] self.config._wildcard_vhosts["*.com"] = [vhost] self.config.enhance("*.com", "staple-ocsp", "example/chain.pem") - self.assertFalse(mock_dialog.called) + assert not mock_dialog.called @mock.patch("certbot_nginx._internal.display_ops.select_vhost_multiple") def test_enhance_wildcard_redirect_or_ocsp_no_install(self, mock_dialog): @@ -926,7 +931,7 @@ class NginxConfiguratorTest(util.NginxTest): if 'summer.com' in x.names][0] mock_dialog.return_value = [vhost] self.config.enhance("*.com", "staple-ocsp", "example/chain.pem") - self.assertIs(mock_dialog.called, True) + assert mock_dialog.called is True @mock.patch("certbot_nginx._internal.display_ops.select_vhost_multiple") def test_enhance_wildcard_double_redirect(self, mock_dialog): @@ -935,7 +940,7 @@ class NginxConfiguratorTest(util.NginxTest): if 'summer.com' in x.names][0] self.config._wildcard_redirect_vhosts["*.com"] = [vhost] self.config.enhance("*.com", "redirect") - self.assertFalse(mock_dialog.called) + assert not mock_dialog.called def test_choose_vhosts_wildcard_no_ssl_filter_port(self): # pylint: disable=protected-access @@ -946,19 +951,19 @@ class NginxConfiguratorTest(util.NginxTest): prefer_ssl=False, no_ssl_filter_port='80') # Check that the dialog was called with only port 80 vhosts - self.assertEqual(len(mock_select_vhs.call_args[0][0]), 8) + assert len(mock_select_vhs.call_args[0][0]) == 8 def test_choose_auth_vhosts(self): """choose_auth_vhosts correctly selects duplicative and HTTP/HTTPS vhosts""" http, https = self.config.choose_auth_vhosts('ssl.both.com') - self.assertEqual(len(http), 4) - self.assertEqual(len(https), 2) - self.assertEqual(http[0].names, {'ssl.both.com'}) - self.assertEqual(http[1].names, {'ssl.both.com'}) - self.assertEqual(http[2].names, {'ssl.both.com'}) - self.assertEqual(http[3].names, {'*.both.com'}) - self.assertEqual(https[0].names, {'ssl.both.com'}) - self.assertEqual(https[1].names, {'*.both.com'}) + assert len(http) == 4 + assert len(https) == 2 + assert http[0].names == {'ssl.both.com'} + assert http[1].names == {'ssl.both.com'} + assert http[2].names == {'ssl.both.com'} + assert http[3].names == {'*.both.com'} + assert https[0].names == {'ssl.both.com'} + assert https[1].names == {'*.both.com'} class InstallSslOptionsConfTest(util.NginxTest): @@ -978,15 +983,15 @@ class InstallSslOptionsConfTest(util.NginxTest): return crypto_util.sha256sum(self.config.mod_ssl_conf_src) def _assert_current_file(self): - self.assertTrue(os.path.isfile(self.config.mod_ssl_conf)) - self.assertEqual(crypto_util.sha256sum(self.config.mod_ssl_conf), - self._current_ssl_options_hash()) + assert os.path.isfile(self.config.mod_ssl_conf) + assert crypto_util.sha256sum(self.config.mod_ssl_conf) == \ + self._current_ssl_options_hash() def test_no_file(self): # prepare should have placed a file there self._assert_current_file() os.remove(self.config.mod_ssl_conf) - self.assertFalse(os.path.isfile(self.config.mod_ssl_conf)) + assert not os.path.isfile(self.config.mod_ssl_conf) self._call() self._assert_current_file() @@ -1026,12 +1031,12 @@ class InstallSslOptionsConfTest(util.NginxTest): mod_ssl_conf.write("a new line for the wrong hash\n") with mock.patch("certbot.plugins.common.logger") as mock_logger: self._call() - self.assertFalse(mock_logger.warning.called) - self.assertTrue(os.path.isfile(self.config.mod_ssl_conf)) - self.assertEqual(crypto_util.sha256sum(self.config.mod_ssl_conf_src), - self._current_ssl_options_hash()) - self.assertNotEqual(crypto_util.sha256sum(self.config.mod_ssl_conf), - self._current_ssl_options_hash()) + assert not mock_logger.warning.called + assert os.path.isfile(self.config.mod_ssl_conf) + assert crypto_util.sha256sum(self.config.mod_ssl_conf_src) == \ + self._current_ssl_options_hash() + assert crypto_util.sha256sum(self.config.mod_ssl_conf) != \ + self._current_ssl_options_hash() def test_manually_modified_past_file_warns(self): with open(self.config.mod_ssl_conf, "a") as mod_ssl_conf: @@ -1040,24 +1045,21 @@ class InstallSslOptionsConfTest(util.NginxTest): f.write("hashofanoldversion") with mock.patch("certbot.plugins.common.logger") as mock_logger: self._call() - self.assertEqual( - mock_logger.warning.call_args[0][0], - "%s has been manually modified; updated file " - "saved to %s. We recommend updating %s for security purposes.") - self.assertEqual(crypto_util.sha256sum(self.config.mod_ssl_conf_src), - self._current_ssl_options_hash()) + assert mock_logger.warning.call_args[0][0] == \ + "%s has been manually modified; updated file " \ + "saved to %s. We recommend updating %s for security purposes." + assert crypto_util.sha256sum(self.config.mod_ssl_conf_src) == \ + self._current_ssl_options_hash() # only print warning once with mock.patch("certbot.plugins.common.logger") as mock_logger: self._call() - self.assertFalse(mock_logger.warning.called) + assert not mock_logger.warning.called def test_current_file_hash_in_all_hashes(self): from certbot_nginx._internal.constants import ALL_SSL_OPTIONS_HASHES - self.assertIn( - self._current_ssl_options_hash(), ALL_SSL_OPTIONS_HASHES, - "Constants.ALL_SSL_OPTIONS_HASHES must be appended" + assert self._current_ssl_options_hash() in ALL_SSL_OPTIONS_HASHES, \ + "Constants.ALL_SSL_OPTIONS_HASHES must be appended" \ " with the sha256 hash of self.config.mod_ssl_conf when it is updated." - ) def test_ssl_config_files_hash_in_all_hashes(self): """ @@ -1076,37 +1078,35 @@ class InstallSslOptionsConfTest(util.NginxTest): "options-ssl-nginx-old.conf", "options-ssl-nginx-tls12-only.conf") ] - self.assertTrue(all_files) + assert all_files for one_file in all_files: file_hash = crypto_util.sha256sum(one_file) - self.assertIn( - file_hash, ALL_SSL_OPTIONS_HASHES, - f"Constants.ALL_SSL_OPTIONS_HASHES must be appended with the sha256 " + assert file_hash in ALL_SSL_OPTIONS_HASHES, \ + f"Constants.ALL_SSL_OPTIONS_HASHES must be appended with the sha256 " \ f"hash of {one_file} when it is updated." - ) def test_nginx_version_uses_correct_config(self): self.config.version = (1, 5, 8) self.config.openssl_version = "1.0.2g" # shouldn't matter - self.assertEqual(os.path.basename(self.config.mod_ssl_conf_src), - "options-ssl-nginx-old.conf") + assert os.path.basename(self.config.mod_ssl_conf_src) == \ + "options-ssl-nginx-old.conf" self._call() self._assert_current_file() self.config.version = (1, 5, 9) self.config.openssl_version = "1.0.2l" - self.assertEqual(os.path.basename(self.config.mod_ssl_conf_src), - "options-ssl-nginx-tls12-only.conf") + assert os.path.basename(self.config.mod_ssl_conf_src) == \ + "options-ssl-nginx-tls12-only.conf" self._call() self._assert_current_file() self.config.version = (1, 13, 0) - self.assertEqual(os.path.basename(self.config.mod_ssl_conf_src), - "options-ssl-nginx.conf") + assert os.path.basename(self.config.mod_ssl_conf_src) == \ + "options-ssl-nginx.conf" self._call() self._assert_current_file() self.config.version = (1, 13, 0) self.config.openssl_version = "1.0.2k" - self.assertEqual(os.path.basename(self.config.mod_ssl_conf_src), - "options-ssl-nginx-tls13-session-tix-on.conf") + assert os.path.basename(self.config.mod_ssl_conf_src) == \ + "options-ssl-nginx-tls13-session-tix-on.conf" class DetermineDefaultServerRootTest(certbot_test_util.ConfigTestCase): @@ -1128,10 +1128,10 @@ class DetermineDefaultServerRootTest(certbot_test_util.ConfigTestCase): server_root = self._call() if expect_both_values: - self.assertIn("/usr/local/etc/nginx", server_root) - self.assertIn("/etc/nginx", server_root) + assert "/usr/local/etc/nginx" in server_root + assert "/etc/nginx" in server_root else: - self.assertIn(server_root, ("/etc/nginx", "/usr/local/etc/nginx")) + assert server_root in ("/etc/nginx", "/usr/local/etc/nginx") if __name__ == "__main__": diff --git a/certbot-nginx/tests/display_ops_test.py b/certbot-nginx/tests/display_ops_test.py index 7c3e878bc..4e9266c52 100644 --- a/certbot-nginx/tests/display_ops_test.py +++ b/certbot-nginx/tests/display_ops_test.py @@ -20,7 +20,7 @@ class SelectVhostMultiTest(util.NginxTest): self.vhosts = nparser.get_vhosts() def test_select_no_input(self): - self.assertFalse(select_vhost_multiple([])) + assert not select_vhost_multiple([]) @certbot_util.patch_display_util() def test_select_correct(self, mock_util): @@ -30,16 +30,16 @@ class SelectVhostMultiTest(util.NginxTest): vhs = select_vhost_multiple([self.vhosts[3], self.vhosts[2], self.vhosts[1]]) - self.assertIn(self.vhosts[2], vhs) - self.assertIn(self.vhosts[3], vhs) - self.assertNotIn(self.vhosts[1], vhs) + assert self.vhosts[2] in vhs + assert self.vhosts[3] in vhs + assert self.vhosts[1] not in vhs @certbot_util.patch_display_util() def test_select_cancel(self, mock_util): mock_util().checklist.return_value = (display_util.CANCEL, "whatever") vhs = select_vhost_multiple([self.vhosts[2], self.vhosts[3]]) - self.assertEqual(len(vhs), 0) - self.assertEqual(vhs, []) + assert len(vhs) == 0 + assert vhs == [] if __name__ == "__main__": diff --git a/certbot-nginx/tests/http_01_test.py b/certbot-nginx/tests/http_01_test.py index 2a03255a4..e0809f68a 100644 --- a/certbot-nginx/tests/http_01_test.py +++ b/certbot-nginx/tests/http_01_test.py @@ -60,7 +60,7 @@ class HttpPerformTest(util.NginxTest): def test_perform0(self): responses = self.http01.perform() - self.assertEqual([], responses) + assert [] == responses @mock.patch("certbot_nginx._internal.configurator.NginxConfigurator.save") def test_perform1(self, mock_save): @@ -69,8 +69,8 @@ class HttpPerformTest(util.NginxTest): responses = self.http01.perform() - self.assertEqual([response], responses) - self.assertEqual(mock_save.call_count, 1) + assert [response] == responses + assert mock_save.call_count == 1 def test_perform2(self): acme_responses = [] @@ -80,9 +80,9 @@ class HttpPerformTest(util.NginxTest): http_responses = self.http01.perform() - self.assertEqual(len(http_responses), 5) + assert len(http_responses) == 5 for i in range(5): - self.assertEqual(http_responses[i], acme_responses[i]) + assert http_responses[i] == acme_responses[i] def test_mod_config(self): self.http01.add_chall(self.achalls[0]) @@ -117,7 +117,7 @@ class HttpPerformTest(util.NginxTest): # Domain has an HTTP and HTTPS vhost # 2 * 'rewrite' + 2 * 'return 200 keyauthz' = 4 - self.assertEqual(mock_add_server_directives.call_count, 4) + assert mock_add_server_directives.call_count == 4 @mock.patch('certbot_nginx._internal.parser.nginxparser.dump') @mock.patch('certbot_nginx._internal.parser.NginxParser.add_server_directives') @@ -127,10 +127,10 @@ class HttpPerformTest(util.NginxTest): self.http01._mod_config() # pylint: disable=protected-access # It should modify the existing HTTPS vhost - self.assertEqual(mock_add_server_directives.call_count, 2) + assert mock_add_server_directives.call_count == 2 # since there was no suitable HTTP vhost or default HTTP vhost, a non-empty one # should have been created and written to the challenge conf file - self.assertNotEqual(mock_dump.call_args[0][0], []) + assert mock_dump.call_args[0][0] != [] @mock.patch('certbot_nginx._internal.parser.NginxParser.add_server_directives') def test_mod_config_deduplicate(self, mock_add_server_directives): @@ -143,14 +143,14 @@ class HttpPerformTest(util.NginxTest): self.http01._mod_config() # pylint: disable=protected-access # Should only get called 5 times, rather than 6, because two vhosts are the same - self.assertEqual(mock_add_server_directives.call_count, 5*2) + assert mock_add_server_directives.call_count == 5*2 def test_mod_config_insert_bucket_directive(self): nginx_conf = self.http01.configurator.parser.abs_path('nginx.conf') expected = ['server_names_hash_bucket_size', '128'] original_conf = self.http01.configurator.parser.parsed[nginx_conf] - self.assertFalse(util.contains_at_depth(original_conf, expected, 2)) + assert not util.contains_at_depth(original_conf, expected, 2) self.http01.add_chall(self.achalls[0]) self.http01._mod_config() # pylint: disable=protected-access @@ -158,7 +158,7 @@ class HttpPerformTest(util.NginxTest): self.http01.configurator.parser.load() generated_conf = self.http01.configurator.parser.parsed[nginx_conf] - self.assertTrue(util.contains_at_depth(generated_conf, expected, 2)) + assert util.contains_at_depth(generated_conf, expected, 2) def test_mod_config_update_bucket_directive_in_included_file(self): # save old example.com config @@ -182,11 +182,11 @@ class HttpPerformTest(util.NginxTest): expected = ['server_names_hash_bucket_size', '128'] nginx_conf_loc = self.http01.configurator.parser.abs_path('nginx.conf') nginx_conf = self.http01.configurator.parser.parsed[nginx_conf_loc] - self.assertFalse(util.contains_at_depth(nginx_conf, expected, 2)) + assert not util.contains_at_depth(nginx_conf, expected, 2) # is updated in example.com conf generated_conf = self.http01.configurator.parser.parsed[example_com_loc] - self.assertTrue(util.contains_at_depth(generated_conf, expected, 0)) + assert util.contains_at_depth(generated_conf, expected, 0) # put back example.com config with open(example_com_loc, 'w') as f: @@ -198,10 +198,10 @@ class HttpPerformTest(util.NginxTest): # pylint: disable=protected-access ipv6_info.return_value = (True, True) self.http01._default_listen_addresses() - self.assertEqual(ipv6_info.call_count, 1) + assert ipv6_info.call_count == 1 ipv6_info.return_value = (False, False) self.http01._default_listen_addresses() - self.assertEqual(ipv6_info.call_count, 2) + assert ipv6_info.call_count == 2 @mock.patch("certbot_nginx._internal.configurator.NginxConfigurator.ipv6_info") def test_default_listen_addresses_t_t(self, ipv6_info): @@ -210,7 +210,7 @@ class HttpPerformTest(util.NginxTest): addrs = self.http01._default_listen_addresses() http_addr = Addr.fromstring("80") http_ipv6_addr = Addr.fromstring("[::]:80") - self.assertEqual(addrs, [http_addr, http_ipv6_addr]) + assert addrs == [http_addr, http_ipv6_addr] @mock.patch("certbot_nginx._internal.configurator.NginxConfigurator.ipv6_info") def test_default_listen_addresses_t_f(self, ipv6_info): @@ -219,7 +219,7 @@ class HttpPerformTest(util.NginxTest): addrs = self.http01._default_listen_addresses() http_addr = Addr.fromstring("80") http_ipv6_addr = Addr.fromstring("[::]:80 ipv6only=on") - self.assertEqual(addrs, [http_addr, http_ipv6_addr]) + assert addrs == [http_addr, http_ipv6_addr] @mock.patch("certbot_nginx._internal.configurator.NginxConfigurator.ipv6_info") def test_default_listen_addresses_f_f(self, ipv6_info): @@ -227,7 +227,7 @@ class HttpPerformTest(util.NginxTest): ipv6_info.return_value = (False, False) addrs = self.http01._default_listen_addresses() http_addr = Addr.fromstring("80") - self.assertEqual(addrs, [http_addr]) + assert addrs == [http_addr] if __name__ == "__main__": sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-nginx/tests/nginxparser_test.py b/certbot-nginx/tests/nginxparser_test.py index 7f9847db8..b4248b85f 100644 --- a/certbot-nginx/tests/nginxparser_test.py +++ b/certbot-nginx/tests/nginxparser_test.py @@ -25,23 +25,23 @@ class TestRawNginxParser(unittest.TestCase): def test_assignments(self): parsed = RawNginxParser.assignment.parseString('root /test;').asList() - self.assertEqual(parsed, ['root', ' ', '/test']) + assert parsed == ['root', ' ', '/test'] parsed = RawNginxParser.assignment.parseString('root /test;foo bar;').asList() - self.assertEqual(parsed, ['root', ' ', '/test'], ['foo', ' ', 'bar']) + assert parsed == ['root', ' ', '/test'], ['foo', ' ', 'bar'] def test_blocks(self): parsed = RawNginxParser.block.parseString('foo {}').asList() - self.assertEqual(parsed, [['foo', ' '], []]) + assert parsed == [['foo', ' '], []] parsed = RawNginxParser.block.parseString('location /foo{}').asList() - self.assertEqual(parsed, [['location', ' ', '/foo'], []]) + assert parsed == [['location', ' ', '/foo'], []] parsed = RawNginxParser.block.parseString('foo { bar foo ; }').asList() - self.assertEqual(parsed, [['foo', ' '], [[' ', 'bar', ' ', 'foo', ' '], ' ']]) + assert parsed == [['foo', ' '], [[' ', 'bar', ' ', 'foo', ' '], ' ']] def test_nested_blocks(self): parsed = RawNginxParser.block.parseString('foo { bar {} }').asList() block, content = parsed - self.assertEqual(FIRST(content), [[' ', 'bar', ' '], []]) - self.assertEqual(FIRST(block), 'foo') + assert FIRST(content) == [[' ', 'bar', ' '], []] + assert FIRST(block) == 'foo' def test_dump_as_string(self): dumped = dumps(UnspacedList([ @@ -57,24 +57,23 @@ class TestRawNginxParser(unittest.TestCase): ]] ]]])) - self.assertEqual(dumped.split('\n'), - 'user www-data;\n' - 'server {\n' - ' listen 80;\n' - ' server_name foo.com;\n' - ' root /home/ubuntu/sites/foo/;\n' - '\n' - ' location /status {\n' - ' check_status;\n' - '\n' - ' types {\n' - ' image/jpeg jpg;}}}'.split('\n')) + assert dumped.split('\n') == \ + 'user www-data;\n' \ + 'server {\n' \ + ' listen 80;\n' \ + ' server_name foo.com;\n' \ + ' root /home/ubuntu/sites/foo/;\n' \ + '\n' \ + ' location /status {\n' \ + ' check_status;\n' \ + '\n' \ + ' types {\n' \ + ' image/jpeg jpg;}}}'.split('\n') def test_parse_from_file(self): with open(util.get_data_filename('foo.conf')) as handle: parsed = util.filter_comments(load(handle)) - self.assertEqual( - parsed, + assert parsed == \ [['user', 'www-data'], [['http'], [[['server'], [ @@ -92,13 +91,11 @@ class TestRawNginxParser(unittest.TestCase): [['location', '=', r'exact_match\.php$'], []], [['location', '^~', r'ignore_regex\.php$'], []] ]]]]] - ) def test_parse_from_file2(self): with open(util.get_data_filename('edge_cases.conf')) as handle: parsed = util.filter_comments(load(handle)) - self.assertEqual( - parsed, + assert parsed == \ [[['server'], [['server_name', 'simple']]], [['server'], [['server_name', 'with.if'], @@ -113,13 +110,12 @@ class TestRawNginxParser(unittest.TestCase): 'Cache-Control', '\'public, must-revalidate, proxy-revalidate\'', '"test,;{}"', 'foo'], ['blah', '"hello;world"'], - ['try_files', '$uri', '@rewrites']]]]]]) + ['try_files', '$uri', '@rewrites']]]]]] def test_parse_from_file3(self): with open(util.get_data_filename('multiline_quotes.conf')) as handle: parsed = util.filter_comments(load(handle)) - self.assertEqual( - parsed, + assert parsed == \ [[['http'], [[['server'], [['listen', '*:443'], @@ -131,11 +127,12 @@ class TestRawNginxParser(unittest.TestCase): 'if ngx.arg[2] then\n' ' ' 'ngx.var.resp_body = ngx.ctx.buffered\n' - ' end\'']]]]]]]]) + ' end\'']]]]]]]] def test_abort_on_parse_failure(self): with open(util.get_data_filename('broken.conf')) as handle: - self.assertRaises(ParseException, load, handle) + with pytest.raises(ParseException): + load(handle) def test_dump_as_file(self): with open(util.get_data_filename('nginx.conf')) as handle: @@ -156,7 +153,7 @@ class TestRawNginxParser(unittest.TestCase): dump(parsed, f) f.seek(0) parsed_new = load(f) - self.assertEqual(parsed, parsed_new) + assert parsed == parsed_new def test_comments(self): with open(util.get_data_filename('minimalistic_comments.conf')) as handle: @@ -167,8 +164,8 @@ class TestRawNginxParser(unittest.TestCase): f.seek(0) parsed_new = load(f) - self.assertEqual(parsed, parsed_new) - self.assertEqual(parsed_new, [ + assert parsed == parsed_new + assert parsed_new == [ ['#', " Use bar.conf when it's a full moon!"], ['include', 'foo.conf'], ['#', ' Kilroy was here'], @@ -179,44 +176,44 @@ class TestRawNginxParser(unittest.TestCase): ['#', ''], ['listen', '1234'], ['#', ' listen 80;']]], - ]) + ] def test_issue_518(self): parsed = loads('if ($http_accept ~* "webp") { set $webp "true"; }') - self.assertEqual(parsed, [ + assert parsed == [ [['if', '($http_accept', '~*', '"webp")'], [['set', '$webp', '"true"']]] - ]) + ] def test_comment_in_block(self): parsed = loads("""http { # server{ }""") - self.assertEqual(parsed, [ + assert parsed == [ [['http'], [['#', ' server{']]] - ]) + ] def test_access_log(self): # see issue #3798 parsed = loads('access_log syslog:server=unix:/dev/log,facility=auth,' 'tag=nginx_post,severity=info custom;') - self.assertEqual(parsed, [ + assert parsed == [ ['access_log', 'syslog:server=unix:/dev/log,facility=auth,tag=nginx_post,severity=info', 'custom'] - ]) + ] def test_add_header(self): # see issue #3798 parsed = loads('add_header Cache-Control no-cache,no-store,must-revalidate,max-age=0;') - self.assertEqual(parsed, [ + assert parsed == [ ['add_header', 'Cache-Control', 'no-cache,no-store,must-revalidate,max-age=0'] - ]) + ] def test_map_then_assignment_in_block(self): # see issue #3798 @@ -230,7 +227,7 @@ class TestRawNginxParser(unittest.TestCase): one; }""" parsed = loads(test_str) - self.assertEqual(parsed, [ + assert parsed == [ [['http'], [ [['map', '$http_upgrade', '$connection_upgrade'], [ ['default', 'upgrade'], @@ -240,17 +237,17 @@ class TestRawNginxParser(unittest.TestCase): ]], ['one'] ]] - ]) + ] def test_variable_name(self): parsed = loads('try_files /typo3temp/tx_ncstaticfilecache/' '$host${request_uri}index.html @nocache;') - self.assertEqual(parsed, [ + assert parsed == [ ['try_files', '/typo3temp/tx_ncstaticfilecache/$host${request_uri}index.html', '@nocache'] - ]) + ] def test_weird_blocks(self): test = r""" @@ -281,7 +278,7 @@ class TestRawNginxParser(unittest.TestCase): proxy_set_header X-Origin-URI ${scheme}://${http_host}/$request_uri; """ parsed = loads(test) - self.assertEqual(parsed, [[['if', '($http_user_agent', '~', 'MSIE)'], + assert parsed == [[['if', '($http_user_agent', '~', 'MSIE)'], [['rewrite', '^(.*)$', '/msie/$1', 'break']]], [['if', '($http_cookie', '~*', '"id=([^;]+)(?:;|$)")'], [['set', '$id', '$1']]], [['if', '($request_method', '=', 'POST)'], [['return', '405']]], @@ -291,18 +288,17 @@ class TestRawNginxParser(unittest.TestCase): [['location', '~', '^/users/(.+\\.(?:gif|jpe?g|png))$'], [['alias', '/data/w3/images/$1']]], ['proxy_set_header', 'X-Origin-URI', '${scheme}://${http_host}/$request_uri']] - ) def test_edge_cases(self): # quotes parsed = loads(r'"hello\""; # blah "heh heh"') - self.assertEqual(parsed, [['"hello\\""'], ['#', ' blah "heh heh"']]) + assert parsed == [['"hello\\""'], ['#', ' blah "heh heh"']] # if with comment parsed = loads("""if ($http_cookie ~* "id=([^;]+)(?:;|$)") { # blah ) }""") - self.assertEqual(parsed, [[['if', '($http_cookie', '~*', '"id=([^;]+)(?:;|$)")'], - [['#', ' blah )']]]]) + assert parsed == [[['if', '($http_cookie', '~*', '"id=([^;]+)(?:;|$)")'], + [['#', ' blah )']]]] # end paren test = """ @@ -317,7 +313,7 @@ class TestRawNginxParser(unittest.TestCase): one"test"one; """ parsed = loads(test) - self.assertEqual(parsed, [ + assert parsed == [ ['one"test"'], ['("two")'], ['"test")red'], @@ -327,9 +323,11 @@ class TestRawNginxParser(unittest.TestCase): ['one"'], ['one"test'], ['one"test"one'] - ]) - self.assertRaises(ParseException, loads, r'"test"one;') # fails - self.assertRaises(ParseException, loads, r'"test;') # fails + ] + with pytest.raises(ParseException): + loads(r'"test"one;') # fails + with pytest.raises(ParseException): + loads(r'"test;') # fails # newlines test = """ @@ -339,27 +337,30 @@ class TestRawNginxParser(unittest.TestCase): baz.example.com qux.example.com; """ parsed = loads(test) - self.assertEqual(parsed, [ + assert parsed == [ ['server_name', 'foo.example.com', 'bar.example.com', 'baz.example.com', 'qux.example.com'], ['server_name', 'foo.example.com', 'bar.example.com', 'baz.example.com', 'qux.example.com'] - ]) + ] # variable weirdness parsed = loads("directive $var ${var} $ ${};") - self.assertEqual(parsed, [['directive', '$var', '${var}', '$', '${}']]) - self.assertRaises(ParseException, loads, "server {server_name test.com};") - self.assertEqual(loads("blag${dfgdfg};"), [['blag${dfgdfg}']]) - self.assertRaises(ParseException, loads, "blag${dfgdf{g};") + assert parsed == [['directive', '$var', '${var}', '$', '${}']] + with pytest.raises(ParseException): + loads("server {server_name test.com};") + assert loads("blag${dfgdfg};") == [['blag${dfgdfg}']] + with pytest.raises(ParseException): + loads("blag${dfgdf{g};") # empty file parsed = loads("") - self.assertEqual(parsed, []) + assert parsed == [] def test_lua(self): # https://github.com/certbot/certbot/issues/9066 - self.assertRaises(UnsupportedDirectiveException, loads, """ + with pytest.raises(UnsupportedDirectiveException): + loads(""" location /foo { content_by_lua_block { ngx.say('Hello World') @@ -368,7 +369,8 @@ class TestRawNginxParser(unittest.TestCase): """) # Without leading whitespace - self.assertRaises(UnsupportedDirectiveException, loads, """ + with pytest.raises(UnsupportedDirectiveException): + loads(""" location /foo {content_by_lua_block { ngx.say('Hello World') } @@ -383,8 +385,7 @@ class TestRawNginxParser(unittest.TestCase): # } } """) - self.assertEqual( - parsed, + assert parsed == \ [ [['location', '/foo'], [['server_name', 'content_by_lua_block'], @@ -392,7 +393,7 @@ class TestRawNginxParser(unittest.TestCase): ['#', " ngx.say('Hello World')"], ['#', ' }'] ]] - ]) + ] # *_by_lua should parse successfully. parsed = loads(""" @@ -407,8 +408,7 @@ class TestRawNginxParser(unittest.TestCase): '; } """) - self.assertEqual( - parsed, + assert parsed == \ [ [['location', '/'], [['set', '$a', '32'], @@ -419,7 +419,6 @@ class TestRawNginxParser(unittest.TestCase): ['content_by_lua', '\'\n ngx.say("foo");\n \''] ]] ] - ) class TestUnspacedList(unittest.TestCase): """Test the UnspacedList data structure""" @@ -432,42 +431,44 @@ class TestUnspacedList(unittest.TestCase): self.ul2 = UnspacedList(self.l2) def test_construction(self): - self.assertEqual(self.ul, ["things", "quirk"]) - self.assertEqual(self.ul2, ["y"]) + assert self.ul == ["things", "quirk"] + assert self.ul2 == ["y"] def test_append(self): ul3 = copy.deepcopy(self.ul) ul3.append("wise") - self.assertEqual(ul3, ["things", "quirk", "wise"]) - self.assertEqual(ul3.spaced, self.a + ["wise"]) + assert ul3 == ["things", "quirk", "wise"] + assert ul3.spaced == self.a + ["wise"] def test_add(self): ul3 = self.ul + self.ul2 - self.assertEqual(ul3, ["things", "quirk", "y"]) - self.assertEqual(ul3.spaced, self.a + self.b) - self.assertEqual(self.ul.spaced, self.a) + assert ul3 == ["things", "quirk", "y"] + assert ul3.spaced == self.a + self.b + assert self.ul.spaced == self.a ul3 = self.ul + self.l2 - self.assertEqual(ul3, ["things", "quirk", "y"]) - self.assertEqual(ul3.spaced, self.a + self.b) + assert ul3 == ["things", "quirk", "y"] + assert ul3.spaced == self.a + self.b def test_extend(self): ul3 = copy.deepcopy(self.ul) ul3.extend(self.ul2) - self.assertEqual(ul3, ["things", "quirk", "y"]) - self.assertEqual(ul3.spaced, self.a + self.b) - self.assertEqual(self.ul.spaced, self.a) + assert ul3 == ["things", "quirk", "y"] + assert ul3.spaced == self.a + self.b + assert self.ul.spaced == self.a def test_set(self): ul3 = copy.deepcopy(self.ul) ul3[0] = "zither" l = ["\n ", "zather", "zest"] ul3[1] = UnspacedList(l) - self.assertEqual(ul3, ["zither", ["zather", "zest"]]) - self.assertEqual(ul3.spaced, [self.a[0], "zither", " ", l]) + assert ul3 == ["zither", ["zather", "zest"]] + assert ul3.spaced == [self.a[0], "zither", " ", l] def test_get(self): - self.assertRaises(IndexError, self.ul2.__getitem__, 2) - self.assertRaises(IndexError, self.ul2.__getitem__, -3) + with pytest.raises(IndexError): + self.ul2.__getitem__(2) + with pytest.raises(IndexError): + self.ul2.__getitem__(-3) def test_insert(self): x = UnspacedList( @@ -477,17 +478,17 @@ class TestUnspacedList(unittest.TestCase): ['\n ', 'server_name', ' ', 'example.*'], '\n', ['listen', ' ', '5001', ' ', 'ssl']]) x.insert(5, "FROGZ") - self.assertEqual(x, + assert x == \ [['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', '.example.com'], ['server_name', 'example.*'], - ['listen', '5001', 'ssl'], 'FROGZ']) - self.assertEqual(x.spaced, + ['listen', '5001', 'ssl'], 'FROGZ'] + assert x.spaced == \ [['\n ', 'listen', ' ', '69.50.225.155:9000'], ['\n ', 'listen', ' ', '127.0.0.1'], ['\n ', 'server_name', ' ', '.example.com'], ['\n ', 'server_name', ' ', 'example.*'], '\n', ['listen', ' ', '5001', ' ', 'ssl'], - 'FROGZ']) + 'FROGZ'] def test_rawlists(self): ul3 = copy.deepcopy(self.ul) @@ -495,18 +496,18 @@ class TestUnspacedList(unittest.TestCase): ul3.append("why") ul3.extend(["did", "whether"]) del ul3[2] - self.assertEqual(ul3, ["some", "things", "why", "did", "whether"]) + assert ul3 == ["some", "things", "why", "did", "whether"] def test_is_dirty(self): - self.assertIs(self.ul2.is_dirty(), False) + assert self.ul2.is_dirty() is False ul3 = UnspacedList([]) ul3.append(self.ul) - self.assertIs(self.ul.is_dirty(), False) - self.assertIs(ul3.is_dirty(), True) + assert self.ul.is_dirty() is False + assert ul3.is_dirty() is True ul4 = UnspacedList([[1], [2, 3, 4]]) - self.assertIs(ul4.is_dirty(), False) + assert ul4.is_dirty() is False ul4[1][2] = 5 - self.assertIs(ul4.is_dirty(), True) + assert ul4.is_dirty() is True if __name__ == '__main__': diff --git a/certbot-nginx/tests/obj_test.py b/certbot-nginx/tests/obj_test.py index ef8255ee9..43ac31d27 100644 --- a/certbot-nginx/tests/obj_test.py +++ b/certbot-nginx/tests/obj_test.py @@ -20,65 +20,65 @@ class AddrTest(unittest.TestCase): self.addr8 = Addr.fromstring("*:80 default ssl") def test_fromstring(self): - self.assertEqual(self.addr1.get_addr(), "192.168.1.1") - self.assertEqual(self.addr1.get_port(), "") - self.assertIs(self.addr1.ssl, False) - self.assertIs(self.addr1.default, False) + assert self.addr1.get_addr() == "192.168.1.1" + assert self.addr1.get_port() == "" + assert self.addr1.ssl is False + assert self.addr1.default is False - self.assertEqual(self.addr2.get_addr(), "192.168.1.1") - self.assertEqual(self.addr2.get_port(), "*") - self.assertIs(self.addr2.ssl, True) - self.assertIs(self.addr2.default, False) + assert self.addr2.get_addr() == "192.168.1.1" + assert self.addr2.get_port() == "*" + assert self.addr2.ssl is True + assert self.addr2.default is False - self.assertEqual(self.addr3.get_addr(), "192.168.1.1") - self.assertEqual(self.addr3.get_port(), "80") - self.assertIs(self.addr3.ssl, False) - self.assertIs(self.addr3.default, False) + assert self.addr3.get_addr() == "192.168.1.1" + assert self.addr3.get_port() == "80" + assert self.addr3.ssl is False + assert self.addr3.default is False - self.assertEqual(self.addr4.get_addr(), "*") - self.assertEqual(self.addr4.get_port(), "80") - self.assertIs(self.addr4.ssl, True) - self.assertIs(self.addr4.default, True) + assert self.addr4.get_addr() == "*" + assert self.addr4.get_port() == "80" + assert self.addr4.ssl is True + assert self.addr4.default is True - self.assertEqual(self.addr5.get_addr(), "myhost") - self.assertEqual(self.addr5.get_port(), "") - self.assertIs(self.addr5.ssl, False) - self.assertIs(self.addr5.default, False) + assert self.addr5.get_addr() == "myhost" + assert self.addr5.get_port() == "" + assert self.addr5.ssl is False + assert self.addr5.default is False - self.assertEqual(self.addr6.get_addr(), "") - self.assertEqual(self.addr6.get_port(), "80") - self.assertIs(self.addr6.ssl, False) - self.assertIs(self.addr6.default, True) + assert self.addr6.get_addr() == "" + assert self.addr6.get_port() == "80" + assert self.addr6.ssl is False + assert self.addr6.default is True - self.assertIs(self.addr8.default, True) + assert self.addr8.default is True - self.assertIsNone(self.addr7) + assert self.addr7 is None def test_str(self): - self.assertEqual(str(self.addr1), "192.168.1.1") - self.assertEqual(str(self.addr2), "192.168.1.1:* ssl") - self.assertEqual(str(self.addr3), "192.168.1.1:80") - self.assertEqual(str(self.addr4), "*:80 default_server ssl") - self.assertEqual(str(self.addr5), "myhost") - self.assertEqual(str(self.addr6), "80 default_server") - self.assertEqual(str(self.addr8), "*:80 default_server ssl") + assert str(self.addr1) == "192.168.1.1" + assert str(self.addr2) == "192.168.1.1:* ssl" + assert str(self.addr3) == "192.168.1.1:80" + assert str(self.addr4) == "*:80 default_server ssl" + assert str(self.addr5) == "myhost" + assert str(self.addr6) == "80 default_server" + assert str(self.addr8) == "*:80 default_server ssl" def test_to_string(self): - self.assertEqual(self.addr1.to_string(), "192.168.1.1") - self.assertEqual(self.addr2.to_string(), "192.168.1.1:* ssl") - self.assertEqual(self.addr3.to_string(), "192.168.1.1:80") - self.assertEqual(self.addr4.to_string(), "*:80 default_server ssl") - self.assertEqual(self.addr4.to_string(include_default=False), "*:80 ssl") - self.assertEqual(self.addr5.to_string(), "myhost") - self.assertEqual(self.addr6.to_string(), "80 default_server") - self.assertEqual(self.addr6.to_string(include_default=False), "80") + assert self.addr1.to_string() == "192.168.1.1" + assert self.addr2.to_string() == "192.168.1.1:* ssl" + assert self.addr3.to_string() == "192.168.1.1:80" + assert self.addr4.to_string() == "*:80 default_server ssl" + assert self.addr4.to_string(include_default=False) == "*:80 ssl" + assert self.addr5.to_string() == "myhost" + assert self.addr6.to_string() == "80 default_server" + assert self.addr6.to_string(include_default=False) == "80" def test_eq(self): from certbot_nginx._internal.obj import Addr new_addr1 = Addr.fromstring("192.168.1.1 spdy") - self.assertEqual(self.addr1, new_addr1) - self.assertNotEqual(self.addr1, self.addr2) - self.assertNotEqual(self.addr1, 3333) + assert self.addr1 == new_addr1 + assert self.addr1 != self.addr2 + assert self.addr1 != 3333 def test_equivalent_any_addresses(self): from certbot_nginx._internal.obj import Addr @@ -87,17 +87,16 @@ class AddrTest(unittest.TestCase): "*:80 default_server ssl", "80 default ssl") for first, second in itertools.combinations(any_addresses, 2): - self.assertEqual(Addr.fromstring(first), Addr.fromstring(second)) + assert Addr.fromstring(first) == Addr.fromstring(second) # Also, make sure ports are checked. - self.assertNotEqual(Addr.fromstring(any_addresses[0]), - Addr.fromstring("0.0.0.0:443 default_server ssl")) + assert Addr.fromstring(any_addresses[0]) != \ + Addr.fromstring("0.0.0.0:443 default_server ssl") # And they aren't equivalent to a specified address. for any_address in any_addresses: - self.assertNotEqual( - Addr.fromstring("192.168.1.2:80 default_server ssl"), - Addr.fromstring(any_address)) + assert Addr.fromstring("192.168.1.2:80 default_server ssl") != \ + Addr.fromstring(any_address) def test_set_inclusion(self): from certbot_nginx._internal.obj import Addr @@ -106,7 +105,7 @@ class AddrTest(unittest.TestCase): addr2b = Addr.fromstring("192.168.1.1:* ssl") set_b = {addr1b, addr2b} - self.assertEqual(set_a, set_b) + assert set_a == set_b class VirtualHostTest(unittest.TestCase): @@ -169,21 +168,21 @@ class VirtualHostTest(unittest.TestCase): {Addr.fromstring("localhost blah")}, False, False, {'localhost'}, [], []) - self.assertEqual(vhost1b, self.vhost1) - self.assertEqual(str(vhost1b), str(self.vhost1)) - self.assertNotEqual(vhost1b, 1234) + assert vhost1b == self.vhost1 + assert str(vhost1b) == str(self.vhost1) + assert vhost1b != 1234 def test_str(self): stringified = '\n'.join(['file: filep', 'addrs: localhost', "names: ['localhost']", 'ssl: False', 'enabled: False']) - self.assertEqual(stringified, str(self.vhost1)) + assert stringified == str(self.vhost1) def test_has_header(self): - self.assertIs(self.vhost_has_hsts.has_header('Strict-Transport-Security'), True) - self.assertIs(self.vhost_has_hsts.has_header('Bogus-Header'), False) - self.assertIs(self.vhost1.has_header('Strict-Transport-Security'), False) - self.assertIs(self.vhost1.has_header('Bogus-Header'), False) + assert self.vhost_has_hsts.has_header('Strict-Transport-Security') is True + assert self.vhost_has_hsts.has_header('Bogus-Header') is False + assert self.vhost1.has_header('Strict-Transport-Security') is False + assert self.vhost1.has_header('Bogus-Header') is False def test_contains_list(self): from certbot_nginx._internal.configurator import _test_block_from_block @@ -224,8 +223,8 @@ class VirtualHostTest(unittest.TestCase): "filp", {Addr.fromstring("localhost")}, False, False, {'localhost'}, test_bad_haystack, []) - self.assertTrue(vhost_haystack.contains_list(test_needle)) - self.assertFalse(vhost_bad_haystack.contains_list(test_needle)) + assert vhost_haystack.contains_list(test_needle) + assert not vhost_bad_haystack.contains_list(test_needle) if __name__ == "__main__": diff --git a/certbot-nginx/tests/parser_obj_test.py b/certbot-nginx/tests/parser_obj_test.py index e0a8114a9..7503897cc 100644 --- a/certbot-nginx/tests/parser_obj_test.py +++ b/certbot-nginx/tests/parser_obj_test.py @@ -13,53 +13,53 @@ from certbot_nginx._internal.parser_obj import parse_raw class CommentHelpersTest(unittest.TestCase): def test_is_comment(self): from certbot_nginx._internal.parser_obj import _is_comment - self.assertTrue(_is_comment(parse_raw(['#']))) - self.assertTrue(_is_comment(parse_raw(['#', ' literally anything else']))) - self.assertFalse(_is_comment(parse_raw(['not', 'even', 'a', 'comment']))) + assert _is_comment(parse_raw(['#'])) + assert _is_comment(parse_raw(['#', ' literally anything else'])) + assert not _is_comment(parse_raw(['not', 'even', 'a', 'comment'])) def test_is_certbot_comment(self): from certbot_nginx._internal.parser_obj import _is_certbot_comment - self.assertTrue(_is_certbot_comment( - parse_raw(COMMENT_BLOCK))) - self.assertFalse(_is_certbot_comment( - parse_raw(['#', ' not a certbot comment']))) - self.assertFalse(_is_certbot_comment( - parse_raw(['#', ' managed by Certbot', ' also not a certbot comment']))) - self.assertFalse(_is_certbot_comment( - parse_raw(['not', 'even', 'a', 'comment']))) + assert _is_certbot_comment( + parse_raw(COMMENT_BLOCK)) + assert not _is_certbot_comment( + parse_raw(['#', ' not a certbot comment'])) + assert not _is_certbot_comment( + parse_raw(['#', ' managed by Certbot', ' also not a certbot comment'])) + assert not _is_certbot_comment( + parse_raw(['not', 'even', 'a', 'comment'])) def test_certbot_comment(self): from certbot_nginx._internal.parser_obj import _certbot_comment from certbot_nginx._internal.parser_obj import _is_certbot_comment comment = _certbot_comment(None) - self.assertTrue(_is_certbot_comment(comment)) - self.assertEqual(comment.dump(), COMMENT_BLOCK) - self.assertEqual(comment.dump(True), [' '] + COMMENT_BLOCK) - self.assertEqual(_certbot_comment(None, 2).dump(True), [' '] + COMMENT_BLOCK) + assert _is_certbot_comment(comment) + assert comment.dump() == COMMENT_BLOCK + assert comment.dump(True) == [' '] + COMMENT_BLOCK + assert _certbot_comment(None, 2).dump(True) == [' '] + COMMENT_BLOCK class ParsingHooksTest(unittest.TestCase): def test_is_sentence(self): from certbot_nginx._internal.parser_obj import Sentence - self.assertFalse(Sentence.should_parse([])) - self.assertTrue(Sentence.should_parse([''])) - self.assertTrue(Sentence.should_parse(['word'])) - self.assertTrue(Sentence.should_parse(['two', 'words'])) - self.assertFalse(Sentence.should_parse([[]])) - self.assertFalse(Sentence.should_parse(['word', []])) + assert not Sentence.should_parse([]) + assert Sentence.should_parse(['']) + assert Sentence.should_parse(['word']) + assert Sentence.should_parse(['two', 'words']) + assert not Sentence.should_parse([[]]) + assert not Sentence.should_parse(['word', []]) def test_is_block(self): from certbot_nginx._internal.parser_obj import Block - self.assertFalse(Block.should_parse([])) - self.assertFalse(Block.should_parse([''])) - self.assertFalse(Block.should_parse(['two', 'words'])) - self.assertFalse(Block.should_parse([[[]], []])) - self.assertFalse(Block.should_parse([['block_name'], ['hi', []], []])) - self.assertFalse(Block.should_parse([['block_name'], 'lol'])) - self.assertTrue(Block.should_parse([['block_name'], ['hi', []]])) - self.assertTrue(Block.should_parse([['hello'], []])) - self.assertTrue(Block.should_parse([['block_name'], [['many'], ['statements'], 'here']])) - self.assertTrue(Block.should_parse([['if', ' ', '(whatever)'], ['hi']])) + assert not Block.should_parse([]) + assert not Block.should_parse(['']) + assert not Block.should_parse(['two', 'words']) + assert not Block.should_parse([[[]], []]) + assert not Block.should_parse([['block_name'], ['hi', []], []]) + assert not Block.should_parse([['block_name'], 'lol']) + assert Block.should_parse([['block_name'], ['hi', []]]) + assert Block.should_parse([['hello'], []]) + assert Block.should_parse([['block_name'], [['many'], ['statements'], 'here']]) + assert Block.should_parse([['if', ' ', '(whatever)'], ['hi']]) def test_parse_raw(self): fake_parser1 = mock.Mock() @@ -82,9 +82,11 @@ class ParsingHooksTest(unittest.TestCase): fake_parser1 = mock.Mock() fake_parser1.should_parse = lambda x: False parsing_hooks.return_value = (fake_parser1,) - self.assertRaises(errors.MisconfigurationError, parse_raw, []) + with pytest.raises(errors.MisconfigurationError): + parse_raw([]) parsing_hooks.return_value = () - self.assertRaises(errors.MisconfigurationError, parse_raw, []) + with pytest.raises(errors.MisconfigurationError): + parse_raw([]) def test_parse_raw_passes_add_spaces(self): fake_parser1 = mock.Mock() @@ -102,44 +104,47 @@ class SentenceTest(unittest.TestCase): def test_parse_bad_sentence_raises_error(self): from certbot import errors - self.assertRaises(errors.MisconfigurationError, self.sentence.parse, 'lol') - self.assertRaises(errors.MisconfigurationError, self.sentence.parse, [[]]) - self.assertRaises(errors.MisconfigurationError, self.sentence.parse, [5]) + with pytest.raises(errors.MisconfigurationError): + self.sentence.parse('lol') + with pytest.raises(errors.MisconfigurationError): + self.sentence.parse([[]]) + with pytest.raises(errors.MisconfigurationError): + self.sentence.parse([5]) def test_parse_sentence_words_hides_spaces(self): og_sentence = ['\r\n', 'hello', ' ', ' ', '\t\n ', 'lol', ' ', 'spaces'] self.sentence.parse(og_sentence) - self.assertEqual(self.sentence.words, ['hello', 'lol', 'spaces']) - self.assertEqual(self.sentence.dump(), ['hello', 'lol', 'spaces']) - self.assertEqual(self.sentence.dump(True), og_sentence) + assert self.sentence.words == ['hello', 'lol', 'spaces'] + assert self.sentence.dump() == ['hello', 'lol', 'spaces'] + assert self.sentence.dump(True) == og_sentence def test_parse_sentence_with_add_spaces(self): self.sentence.parse(['hi', 'there'], add_spaces=True) - self.assertEqual(self.sentence.dump(True), ['hi', ' ', 'there']) + assert self.sentence.dump(True) == ['hi', ' ', 'there'] self.sentence.parse(['one', ' ', 'space', 'none'], add_spaces=True) - self.assertEqual(self.sentence.dump(True), ['one', ' ', 'space', ' ', 'none']) + assert self.sentence.dump(True) == ['one', ' ', 'space', ' ', 'none'] def test_iterate(self): expected = [['1', '2', '3']] self.sentence.parse(['1', ' ', '2', ' ', '3']) for i, sentence in enumerate(self.sentence.iterate()): - self.assertEqual(sentence.dump(), expected[i]) + assert sentence.dump() == expected[i] def test_set_tabs(self): self.sentence.parse(['tabs', 'pls'], add_spaces=True) self.sentence.set_tabs() - self.assertEqual(self.sentence.dump(True)[0], '\n ') + assert self.sentence.dump(True)[0] == '\n ' self.sentence.parse(['tabs', 'pls'], add_spaces=True) def test_get_tabs(self): self.sentence.parse(['no', 'tabs']) - self.assertEqual(self.sentence.get_tabs(), '') + assert self.sentence.get_tabs() == '' self.sentence.parse(['\n \n ', 'tabs']) - self.assertEqual(self.sentence.get_tabs(), ' ') + assert self.sentence.get_tabs() == ' ' self.sentence.parse(['\n\t ', 'tabs']) - self.assertEqual(self.sentence.get_tabs(), '\t ') + assert self.sentence.get_tabs() == '\t ' self.sentence.parse(['\n\t \n', 'tabs']) - self.assertEqual(self.sentence.get_tabs(), '') + assert self.sentence.get_tabs() == '' class BlockTest(unittest.TestCase): @@ -152,11 +157,11 @@ class BlockTest(unittest.TestCase): def test_iterate(self): # Iterates itself normally - self.assertEqual(self.bloc, next(self.bloc.iterate())) + assert self.bloc == next(self.bloc.iterate()) # Iterates contents while expanded expected = [self.bloc.dump()] + self.contents for i, elem in enumerate(self.bloc.iterate(expanded=True)): - self.assertEqual(expected[i], elem.dump()) + assert expected[i] == elem.dump() def test_iterate_match(self): # can match on contents while expanded @@ -165,38 +170,41 @@ class BlockTest(unittest.TestCase): expected = [['thing', '1'], ['thing', '2']] for i, elem in enumerate(self.bloc.iterate(expanded=True, match=lambda x: isinstance(x, Sentence) and 'thing' in x.words)): - self.assertEqual(expected[i], elem.dump()) + assert expected[i] == elem.dump() # can match on self - self.assertEqual(self.bloc, next(self.bloc.iterate( + assert self.bloc == next(self.bloc.iterate( expanded=True, - match=lambda x: isinstance(x, Block) and 'server' in x.names))) + match=lambda x: isinstance(x, Block) and 'server' in x.names)) def test_parse_with_added_spaces(self): import copy self.bloc.parse([copy.copy(self.name), self.contents], add_spaces=True) - self.assertEqual(self.bloc.dump(), [self.name, self.contents]) - self.assertEqual(self.bloc.dump(True), [ + assert self.bloc.dump() == [self.name, self.contents] + assert self.bloc.dump(True) == [ ['server', ' ', 'name', ' '], [['thing', ' ', '1'], ['thing', ' ', '2'], - ['another', ' ', 'one']]]) + ['another', ' ', 'one']]] def test_bad_parse_raises_error(self): from certbot import errors - self.assertRaises(errors.MisconfigurationError, self.bloc.parse, [[[]], [[]]]) - self.assertRaises(errors.MisconfigurationError, self.bloc.parse, ['lol']) - self.assertRaises(errors.MisconfigurationError, self.bloc.parse, ['fake', 'news']) + with pytest.raises(errors.MisconfigurationError): + self.bloc.parse([[[]], [[]]]) + with pytest.raises(errors.MisconfigurationError): + self.bloc.parse(['lol']) + with pytest.raises(errors.MisconfigurationError): + self.bloc.parse(['fake', 'news']) def test_set_tabs(self): self.bloc.set_tabs() - self.assertEqual(self.bloc.names.dump(True)[0], '\n ') + assert self.bloc.names.dump(True)[0] == '\n ' for elem in self.bloc.contents.dump(True)[:-1]: - self.assertEqual(elem[0], '\n ') - self.assertEqual(self.bloc.contents.dump(True)[-1][0], '\n') + assert elem[0] == '\n ' + assert self.bloc.contents.dump(True)[-1][0] == '\n' def test_get_tabs(self): self.bloc.parse([[' \n \t', 'lol'], []]) - self.assertEqual(self.bloc.get_tabs(), ' \t') + assert self.bloc.get_tabs() == ' \t' class StatementsTest(unittest.TestCase): def setUp(self): @@ -218,7 +226,7 @@ class StatementsTest(unittest.TestCase): self.statements.parse(self.raw) self.statements.set_tabs() for statement in self.statements.iterate(): - self.assertEqual(statement.dump(True)[0], '\n ') + assert statement.dump(True)[0] == '\n ' def test_set_tabs_with_parent(self): # Trailing whitespace should inherit from parent tabbing. @@ -227,35 +235,36 @@ class StatementsTest(unittest.TestCase): self.statements.parent.get_tabs.return_value = '\t\t' self.statements.set_tabs() for statement in self.statements.iterate(): - self.assertEqual(statement.dump(True)[0], '\n ') - self.assertEqual(self.statements.dump(True)[-1], '\n\t\t') + assert statement.dump(True)[0] == '\n ' + assert self.statements.dump(True)[-1] == '\n\t\t' def test_get_tabs(self): self.raw[0].insert(0, '\n \n \t') self.statements.parse(self.raw) - self.assertEqual(self.statements.get_tabs(), ' \t') + assert self.statements.get_tabs() == ' \t' self.statements.parse([]) - self.assertEqual(self.statements.get_tabs(), '') + assert self.statements.get_tabs() == '' def test_parse_with_added_spaces(self): self.statements.parse(self.raw, add_spaces=True) - self.assertEqual(self.statements.dump(True)[0], ['sentence', ' ', 'one']) + assert self.statements.dump(True)[0] == ['sentence', ' ', 'one'] def test_parse_bad_list_raises_error(self): from certbot import errors - self.assertRaises(errors.MisconfigurationError, self.statements.parse, 'lol not a list') + with pytest.raises(errors.MisconfigurationError): + self.statements.parse('lol not a list') def test_parse_hides_trailing_whitespace(self): self.statements.parse(self.raw + ['\n\n ']) - self.assertIsInstance(self.statements.dump()[-1], list) - self.assertIs(self.statements.dump(True)[-1].isspace(), True) - self.assertEqual(self.statements.dump(True)[-1], '\n\n ') + assert isinstance(self.statements.dump()[-1], list) + assert self.statements.dump(True)[-1].isspace() is True + assert self.statements.dump(True)[-1] == '\n\n ' def test_iterate(self): self.statements.parse(self.raw) expected = [['sentence', 'one'], ['sentence', 'two']] for i, elem in enumerate(self.statements.iterate(match=lambda x: 'sentence' in x)): - self.assertEqual(expected[i], elem.dump()) + assert expected[i] == elem.dump() if __name__ == "__main__": diff --git a/certbot-nginx/tests/parser_test.py b/certbot-nginx/tests/parser_test.py index e9280c787..fea2d9d84 100644 --- a/certbot-nginx/tests/parser_test.py +++ b/certbot-nginx/tests/parser_test.py @@ -29,7 +29,7 @@ class NginxParserTest(util.NginxTest): path = os.path.join(self.temp_dir, "etc_nginx/////" "ubuntu_nginx/../../etc_nginx") nparser = parser.NginxParser(path) - self.assertEqual(nparser.root, self.config_path) + assert nparser.root == self.config_path def test_root_absolute(self): curr_dir = os.getcwd() @@ -39,13 +39,13 @@ class NginxParserTest(util.NginxTest): # self.tempdir to ensure that we stay on the same drive. os.chdir(self.temp_dir) nparser = parser.NginxParser(os.path.relpath(self.config_path)) - self.assertEqual(nparser.root, self.config_path) + assert nparser.root == self.config_path finally: os.chdir(curr_dir) def test_root_no_trailing_slash(self): nparser = parser.NginxParser(self.config_path + os.path.sep) - self.assertEqual(nparser.root, self.config_path) + assert nparser.root == self.config_path def test_load(self): """Test recursive conf file parsing. @@ -53,7 +53,7 @@ class NginxParserTest(util.NginxTest): """ nparser = parser.NginxParser(self.config_path) nparser.load() - self.assertEqual({nparser.abs_path(x) for x in + assert {nparser.abs_path(x) for x in ['foo.conf', 'nginx.conf', 'server.conf', 'mime.types', 'sites-enabled/default', 'sites-enabled/both.com', @@ -64,27 +64,27 @@ class NginxParserTest(util.NginxTest): 'sites-enabled/globalssl.com', 'sites-enabled/ipv6.com', 'sites-enabled/ipv6ssl.com', - 'sites-enabled/example.net']}, - set(nparser.parsed.keys())) - self.assertEqual([['server_name', 'somename', 'alias', 'another.alias']], - nparser.parsed[nparser.abs_path('server.conf')]) - self.assertEqual([[['server'], [['listen', '69.50.225.155:9000'], + 'sites-enabled/example.net']} == \ + set(nparser.parsed.keys()) + assert [['server_name', 'somename', 'alias', 'another.alias']] == \ + nparser.parsed[nparser.abs_path('server.conf')] + assert [[['server'], [['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', '.example.com'], - ['server_name', 'example.*']]]], + ['server_name', 'example.*']]]] == \ nparser.parsed[nparser.abs_path( - 'sites-enabled/example.com')]) + 'sites-enabled/example.com')] def test_abs_path(self): nparser = parser.NginxParser(self.config_path) if os.name != 'nt': - self.assertEqual('/etc/nginx/*', nparser.abs_path('/etc/nginx/*')) - self.assertEqual(os.path.join(self.config_path, 'foo/bar'), - nparser.abs_path('foo/bar')) + assert '/etc/nginx/*' == nparser.abs_path('/etc/nginx/*') + assert os.path.join(self.config_path, 'foo/bar') == \ + nparser.abs_path('foo/bar') else: - self.assertEqual('C:\\etc\\nginx\\*', nparser.abs_path('C:\\etc\\nginx\\*')) - self.assertEqual(os.path.join(self.config_path, 'foo\\bar'), - nparser.abs_path('foo\\bar')) + assert 'C:\\etc\\nginx\\*' == nparser.abs_path('C:\\etc\\nginx\\*') + assert os.path.join(self.config_path, 'foo\\bar') == \ + nparser.abs_path('foo\\bar') def test_filedump(self): @@ -93,14 +93,14 @@ class NginxParserTest(util.NginxTest): # pylint: disable=protected-access parsed = nparser._parse_files(nparser.abs_path( 'sites-enabled/example.com.test')) - self.assertEqual(4, len(glob.glob(nparser.abs_path('*.test')))) - self.assertEqual(10, len( - glob.glob(nparser.abs_path('sites-enabled/*.test')))) - self.assertEqual([[['server'], [['listen', '69.50.225.155:9000'], + assert 4 == len(glob.glob(nparser.abs_path('*.test'))) + assert 10 == len( + glob.glob(nparser.abs_path('sites-enabled/*.test'))) + assert [[['server'], [['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', '.example.com'], - ['server_name', 'example.*']]]], - parsed[0]) + ['server_name', 'example.*']]]] == \ + parsed[0] def test__do_for_subarray(self): # pylint: disable=protected-access @@ -123,7 +123,7 @@ class NginxParserTest(util.NginxTest): len(x) >= 1 and x[0] == 2, lambda x, y, pts=paths: pts.append(y)) - self.assertEqual(paths, result) + assert paths == result def test_get_vhosts_global_ssl(self): nparser = parser.NginxParser(self.config_path) @@ -135,7 +135,7 @@ class NginxParserTest(util.NginxTest): True, True, {'globalssl.com'}, [], [0]) globalssl_com = [x for x in vhosts if 'globalssl.com' in x.filep][0] - self.assertEqual(vhost, globalssl_com) + assert vhost == globalssl_com def test_get_vhosts(self): nparser = parser.NginxParser(self.config_path) @@ -177,17 +177,17 @@ class NginxParserTest(util.NginxTest): '*.www.example.com'}, [], [2, 1, 0]) - self.assertEqual(19, len(vhosts)) + assert 19 == len(vhosts) example_com = [x for x in vhosts if 'example.com' in x.filep][0] - self.assertEqual(vhost3, example_com) + assert vhost3 == example_com default = [x for x in vhosts if 'default' in x.filep][0] - self.assertEqual(vhost4, default) + assert vhost4 == default fooconf = [x for x in vhosts if 'foo.conf' in x.filep][0] - self.assertEqual(vhost5, fooconf) + assert vhost5 == fooconf localhost = [x for x in vhosts if 'localhost' in x.names][0] - self.assertEqual(vhost1, localhost) + assert vhost1 == localhost somename = [x for x in vhosts if 'somename' in x.names][0] - self.assertEqual(vhost2, somename) + assert vhost2 == somename def test_has_ssl_on_directive(self): nparser = parser.NginxParser(self.config_path) @@ -196,18 +196,18 @@ class NginxParserTest(util.NginxTest): ['server_name', 'www.example.org'], [['location', '/'], [['root', 'html'], ['index', 'index.html index.htm']]] ], None) - self.assertFalse(nparser.has_ssl_on_directive(mock_vhost)) + assert not nparser.has_ssl_on_directive(mock_vhost) mock_vhost.raw = [['listen', '*:80', 'default_server', 'ssl'], ['server_name', '*.www.foo.com', '*.www.example.com'], ['root', '/home/ubuntu/sites/foo/']] - self.assertFalse(nparser.has_ssl_on_directive(mock_vhost)) + assert not nparser.has_ssl_on_directive(mock_vhost) mock_vhost.raw = [['listen', '80 ssl'], ['server_name', '*.www.foo.com', '*.www.example.com']] - self.assertFalse(nparser.has_ssl_on_directive(mock_vhost)) + assert not nparser.has_ssl_on_directive(mock_vhost) mock_vhost.raw = [['listen', '80'], ['ssl', 'on'], ['server_name', '*.www.foo.com', '*.www.example.com']] - self.assertIs(nparser.has_ssl_on_directive(mock_vhost), True) + assert nparser.has_ssl_on_directive(mock_vhost) is True def test_remove_server_directives(self): nparser = parser.NginxParser(self.config_path) @@ -226,12 +226,12 @@ class NginxParserTest(util.NginxTest): '/etc/ssl/cert2.pem']]) nparser.remove_server_directives(mock_vhost, 'foo') nparser.remove_server_directives(mock_vhost, 'ssl_certificate') - self.assertEqual(nparser.parsed[example_com], + assert nparser.parsed[example_com] == \ [[['server'], [['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', '.example.com'], ['server_name', 'example.*'], - []]]]) + []]]] def test_add_server_directives(self): nparser = parser.NginxParser(self.config_path) @@ -245,7 +245,7 @@ class NginxParserTest(util.NginxTest): '/etc/ssl/cert.pem']]) ssl_re = re.compile(r'\n\s+ssl_certificate /etc/ssl/cert.pem') dump = nginxparser.dumps(nparser.parsed[nparser.abs_path('nginx.conf')]) - self.assertEqual(1, len(re.findall(ssl_re, dump))) + assert 1 == len(re.findall(ssl_re, dump)) example_com = nparser.abs_path('sites-enabled/example.com') names = {'.example.com', 'example.*'} @@ -257,7 +257,7 @@ class NginxParserTest(util.NginxTest): '/etc/ssl/cert2.pem']]) nparser.add_server_directives(mock_vhost, [['foo', 'bar']]) from certbot_nginx._internal.parser import COMMENT - self.assertEqual(nparser.parsed[example_com], + assert nparser.parsed[example_com] == \ [[['server'], [['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', '.example.com'], @@ -266,16 +266,15 @@ class NginxParserTest(util.NginxTest): ['#', COMMENT], ['ssl_certificate', '/etc/ssl/cert2.pem'], ['#', COMMENT], [], [] - ]]]) + ]]] server_conf = nparser.abs_path('server.conf') names = {'alias', 'another.alias', 'somename'} mock_vhost.filep = server_conf mock_vhost.names = names mock_vhost.path = [] - self.assertRaises(errors.MisconfigurationError, - nparser.add_server_directives, - mock_vhost, + with pytest.raises(errors.MisconfigurationError): + nparser.add_server_directives(mock_vhost, [['foo', 'bar'], ['ssl_certificate', '/etc/ssl/cert2.pem']]) @@ -292,7 +291,7 @@ class NginxParserTest(util.NginxTest): [['\n ', 'include', ' ', nparser.abs_path('comment_in_file.conf')]]) from certbot_nginx._internal.parser import COMMENT - self.assertEqual(nparser.parsed[example_com], + assert nparser.parsed[example_com] == \ [[['server'], [['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', '.example.com'], @@ -302,7 +301,6 @@ class NginxParserTest(util.NginxTest): ['include', nparser.abs_path('comment_in_file.conf')], ['#', COMMENT], []]]] -) def test_replace_server_directives(self): nparser = parser.NginxParser(self.config_path) @@ -312,24 +310,22 @@ class NginxParserTest(util.NginxTest): nparser.update_or_add_server_directives( mock_vhost, [['server_name', 'foobar.com']]) from certbot_nginx._internal.parser import COMMENT - self.assertEqual( - nparser.parsed[filep], + assert nparser.parsed[filep] == \ [[['server'], [['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', 'foobar.com'], ['#', COMMENT], ['server_name', 'example.*'], [] - ]]]) + ]]] mock_vhost.names = {'foobar.com', 'example.*'} nparser.update_or_add_server_directives( mock_vhost, [['ssl_certificate', 'cert.pem']]) - self.assertEqual( - nparser.parsed[filep], + assert nparser.parsed[filep] == \ [[['server'], [['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', 'foobar.com'], ['#', COMMENT], ['server_name', 'example.*'], [], ['ssl_certificate', 'cert.pem'], ['#', COMMENT], [], - ]]]) + ]]] def test_get_best_match(self): target_name = 'www.eff.org' @@ -365,8 +361,8 @@ class NginxParserTest(util.NginxTest): ('wildcard_start', '.efF.org')] for i, winner in enumerate(winners): - self.assertEqual(winner, - parser.get_best_match(target_name, names[i])) + assert winner == \ + parser.get_best_match(target_name, names[i]) def test_comment_directive(self): # pylint: disable=protected-access @@ -378,13 +374,13 @@ class NginxParserTest(util.NginxTest): from certbot_nginx._internal.parser import comment_directive comment_directive(block, 1) comment_directive(block, 0) - self.assertEqual(block.spaced, [ + assert block.spaced == [ ["\n", "a", " ", "b", "\n"], COMMENT_BLOCK, "\n", ["c", " ", "d"], COMMENT_BLOCK, - ["\n", "e", " ", "f"]]) + ["\n", "e", " ", "f"]] def test_comment_out_directive(self): server_block = nginxparser.loads(""" @@ -403,7 +399,7 @@ class NginxParserTest(util.NginxTest): _comment_out_directive(block, 4, "blah1") _comment_out_directive(block, 5, "blah2") _comment_out_directive(block, 6, "blah3") - self.assertEqual(block.spaced, [ + assert block.spaced == [ ['\n ', 'listen', ' ', '80'], ['\n ', 'root', ' ', '/var/www/html'], ['\n ', 'index', ' ', 'star.html'], @@ -411,41 +407,41 @@ class NginxParserTest(util.NginxTest): ['\n ', '#', ' ssl_session_timeout 1440m; # duplicated in blah1'], [' ', '#', ' ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # duplicated in blah2'], ['\n\n ', '#', ' ssl_prefer_server_ciphers on; # duplicated in blah3'], - '\n ']) + '\n '] def test_parse_server_raw_ssl(self): server = parser._parse_server_raw([ #pylint: disable=protected-access ['listen', '443'] ]) - self.assertFalse(server['ssl']) + assert not server['ssl'] server = parser._parse_server_raw([ #pylint: disable=protected-access ['listen', '443', 'ssl'] ]) - self.assertTrue(server['ssl']) + assert server['ssl'] server = parser._parse_server_raw([ #pylint: disable=protected-access ['listen', '443'], ['ssl', 'off'] ]) - self.assertFalse(server['ssl']) + assert not server['ssl'] server = parser._parse_server_raw([ #pylint: disable=protected-access ['listen', '443'], ['ssl', 'on'] ]) - self.assertTrue(server['ssl']) + assert server['ssl'] def test_parse_server_raw_unix(self): server = parser._parse_server_raw([ #pylint: disable=protected-access ['listen', 'unix:/var/run/nginx.sock'] ]) - self.assertEqual(len(server['addrs']), 0) + assert len(server['addrs']) == 0 def test_parse_server_global_ssl_applied(self): nparser = parser.NginxParser(self.config_path) server = nparser.parse_server([ ['listen', '443'] ]) - self.assertTrue(server['ssl']) + assert server['ssl'] def test_duplicate_vhost(self): nparser = parser.NginxParser(self.config_path) @@ -456,19 +452,19 @@ class NginxParserTest(util.NginxTest): nparser.filedump(ext='') # check properties of new vhost - self.assertIs(next(iter(new_vhost.addrs)).default, False) - self.assertNotEqual(new_vhost.path, default.path) + assert next(iter(new_vhost.addrs)).default is False + assert new_vhost.path != default.path # check that things are written to file correctly new_nparser = parser.NginxParser(self.config_path) new_vhosts = new_nparser.get_vhosts() new_defaults = [x for x in new_vhosts if 'default' in x.filep] - self.assertEqual(len(new_defaults), 2) + assert len(new_defaults) == 2 new_vhost_parsed = new_defaults[1] - self.assertIs(next(iter(new_vhost_parsed.addrs)).default, False) - self.assertEqual(next(iter(default.names)), next(iter(new_vhost_parsed.names))) - self.assertEqual(len(default.raw), len(new_vhost_parsed.raw)) - self.assertTrue(next(iter(default.addrs)).super_eq(next(iter(new_vhost_parsed.addrs)))) + assert next(iter(new_vhost_parsed.addrs)).default is False + assert next(iter(default.names)) == next(iter(new_vhost_parsed.names)) + assert len(default.raw) == len(new_vhost_parsed.raw) + assert next(iter(default.addrs)).super_eq(next(iter(new_vhost_parsed.addrs))) def test_duplicate_vhost_remove_ipv6only(self): nparser = parser.NginxParser(self.config_path) @@ -479,7 +475,7 @@ class NginxParserTest(util.NginxTest): nparser.filedump(ext='') for addr in new_vhost.addrs: - self.assertFalse(addr.ipv6only) + assert not addr.ipv6only identical_vhost = nparser.duplicate_vhost(ipv6ssl, remove_singleton_listen_params=False) nparser.filedump(ext='') @@ -487,16 +483,16 @@ class NginxParserTest(util.NginxTest): called = False for addr in identical_vhost.addrs: if addr.ipv6: - self.assertTrue(addr.ipv6only) + assert addr.ipv6only called = True - self.assertTrue(called) + assert called def test_valid_unicode_characters(self): nparser = parser.NginxParser(self.config_path) path = nparser.abs_path('valid_unicode_comments.conf') parsed = nparser._parse_files(path) # pylint: disable=protected-access - self.assertEqual(['server'], parsed[0][2][0]) - self.assertEqual(['listen', '80'], parsed[0][2][1][3]) + assert ['server'] == parsed[0][2][0] + assert ['listen', '80'] == parsed[0][2][1][3] def test_valid_unicode_roundtrip(self): """This tests the parser's ability to load and save a config containing Unicode""" @@ -512,18 +508,18 @@ class NginxParserTest(util.NginxTest): path = nparser.abs_path('invalid_unicode_comments.conf') parsed = nparser._parse_files(path) # pylint: disable=protected-access - self.assertEqual([], parsed) - self.assertTrue(any( + assert [] == parsed + assert any( ('invalid character' in output) and ('UTF-8' in output) for output in log.output - )) + ) def test_valid_unicode_characters_in_ssl_options(self): nparser = parser.NginxParser(self.config_path) path = nparser.abs_path('valid_unicode_comments.conf') parsed = parser._parse_ssl_options(path) # pylint: disable=protected-access - self.assertEqual(['server'], parsed[2][0]) - self.assertEqual(['listen', '80'], parsed[2][1][3]) + assert ['server'] == parsed[2][0] + assert ['listen', '80'] == parsed[2][1][3] def test_invalid_unicode_characters_in_ssl_options(self): with self.assertLogs() as log: @@ -531,19 +527,19 @@ class NginxParserTest(util.NginxTest): path = nparser.abs_path('invalid_unicode_comments.conf') parsed = parser._parse_ssl_options(path) # pylint: disable=protected-access - self.assertEqual([], parsed) - self.assertTrue(any( + assert [] == parsed + assert any( ('invalid character' in output) and ('UTF-8' in output) for output in log.output - )) + ) @mock.patch('certbot_nginx._internal.parser.logger.warning') def test_load_unsupported_directive_logged(self, mock_warn): nparser = parser.NginxParser(self.config_path) nparser.config_root = nparser.abs_path('unsupported_directives.conf') nparser.load() - self.assertEqual(mock_warn.call_count, 1) - self.assertIn("which is not supported by Certbot", mock_warn.call_args[0][0]) + assert mock_warn.call_count == 1 + assert "which is not supported by Certbot" in mock_warn.call_args[0][0] if __name__ == "__main__": diff --git a/certbot/tests/account_test.py b/certbot/tests/account_test.py index f076b2096..1cf79d152 100644 --- a/certbot/tests/account_test.py +++ b/certbot/tests/account_test.py @@ -39,21 +39,19 @@ class AccountTest(unittest.TestCase): self.acc_no_meta = Account(self.regr, KEY) def test_init(self): - self.assertEqual(self.regr, self.acc.regr) - self.assertEqual(KEY, self.acc.key) - self.assertEqual(self.meta, self.acc_no_meta.meta) + assert self.regr == self.acc.regr + assert KEY == self.acc.key + assert self.meta == self.acc_no_meta.meta def test_id(self): - self.assertEqual( - self.acc.id, "7adac10320f585ddf118429c0c4af2cd") + assert self.acc.id == "7adac10320f585ddf118429c0c4af2cd" def test_slug(self): - self.assertEqual( - self.acc.slug, "test.certbot.org@2015-07-04T14:04:10Z (7ada)") + assert self.acc.slug == "test.certbot.org@2015-07-04T14:04:10Z (7ada)" def test_repr(self): - self.assertTrue(repr(self.acc).startswith( - " 3 - self.assertEqual(self.mock_auth.cleanup.call_count, 1) + assert self.mock_auth.cleanup.call_count == 1 # Test if list first element is http-01, use typ because it is an achall - self.assertEqual( - self.mock_auth.cleanup.call_args[0][0][0].typ, "http-01") + assert self.mock_auth.cleanup.call_args[0][0][0].typ == "http-01" - self.assertEqual(len(authzr), 1) + assert len(authzr) == 1 def test_name1_http_01_1_acme_2(self): self._test_name1_http_01_1_common() @@ -124,17 +121,17 @@ class HandleAuthorizationsTest(unittest.TestCase): mock_order = mock.MagicMock(authorizations=[authzr]) authzr = self.handler.handle_authorizations(mock_order, self.mock_config) - self.assertEqual(self.mock_net.answer_challenge.call_count, 1) + assert self.mock_net.answer_challenge.call_count == 1 - self.assertEqual(self.mock_net.poll.call_count, 1) + assert self.mock_net.poll.call_count == 1 - self.assertEqual(self.mock_auth.cleanup.call_count, 1) + assert self.mock_auth.cleanup.call_count == 1 cleaned_up_achalls = self.mock_auth.cleanup.call_args[0][0] - self.assertEqual(len(cleaned_up_achalls), 1) - self.assertEqual(cleaned_up_achalls[0].typ, "http-01") + assert len(cleaned_up_achalls) == 1 + assert cleaned_up_achalls[0].typ == "http-01" # Length of authorizations list - self.assertEqual(len(authzr), 1) + assert len(authzr) == 1 def test_name3_http_01_3_common_acme_2(self): authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES), @@ -145,14 +142,14 @@ class HandleAuthorizationsTest(unittest.TestCase): self.mock_net.poll.side_effect = _gen_mock_on_poll() authzr = self.handler.handle_authorizations(mock_order, self.mock_config) - self.assertEqual(self.mock_net.answer_challenge.call_count, 3) + assert self.mock_net.answer_challenge.call_count == 3 # Check poll call - self.assertEqual(self.mock_net.poll.call_count, 3) + assert self.mock_net.poll.call_count == 3 - self.assertEqual(self.mock_auth.cleanup.call_count, 1) + assert self.mock_auth.cleanup.call_count == 1 - self.assertEqual(len(authzr), 3) + assert len(authzr) == 3 def test_debug_challenges(self): config = mock.Mock(debug_challenges=True, verbose_count=0) @@ -166,15 +163,15 @@ class HandleAuthorizationsTest(unittest.TestCase): self.handler.handle_authorizations(mock_order, config) - self.assertEqual(self.mock_net.answer_challenge.call_count, 1) - self.assertEqual(self.mock_display.notification.call_count, 1) - self.assertIn('Pass "-v" for more info', - self.mock_display.notification.call_args[0][0]) - self.assertNotIn(f"http://{authzrs[0].body.identifier.value}/.well-known/acme-challenge/" + - b64encode(authzrs[0].body.challenges[0].chall.token).decode(), - self.mock_display.notification.call_args[0][0]) - self.assertNotIn(b64encode(account_key_thumbprint).decode(), - self.mock_display.notification.call_args[0][0]) + assert self.mock_net.answer_challenge.call_count == 1 + assert self.mock_display.notification.call_count == 1 + assert 'Pass "-v" for more info' in \ + self.mock_display.notification.call_args[0][0] + assert f"http://{authzrs[0].body.identifier.value}/.well-known/acme-challenge/" + \ + b64encode(authzrs[0].body.challenges[0].chall.token).decode() not in \ + self.mock_display.notification.call_args[0][0] + assert b64encode(account_key_thumbprint).decode() not in \ + self.mock_display.notification.call_args[0][0] def test_debug_challenges_verbose(self): config = mock.Mock(debug_challenges=True, verbose_count=1) @@ -192,19 +189,19 @@ class HandleAuthorizationsTest(unittest.TestCase): self.handler.handle_authorizations(mock_order, config) - self.assertEqual(self.mock_net.answer_challenge.call_count, 2) - self.assertEqual(self.mock_display.notification.call_count, 1) - self.assertNotIn('Pass "-v" for more info', - self.mock_display.notification.call_args[0][0]) - self.assertIn(f"http://{authzrs[0].body.identifier.value}/.well-known/acme-challenge/" + - b64encode(authzrs[0].body.challenges[0].chall.token).decode(), - self.mock_display.notification.call_args[0][0]) - self.assertIn(b64encode(account_key_thumbprint).decode(), - self.mock_display.notification.call_args[0][0]) - self.assertIn(f"_acme-challenge.{authzrs[1].body.identifier.value}", - self.mock_display.notification.call_args[0][0]) - self.assertIn(authzrs[1].body.challenges[0].validation(self.mock_account.key), - self.mock_display.notification.call_args[0][0]) + assert self.mock_net.answer_challenge.call_count == 2 + assert self.mock_display.notification.call_count == 1 + assert 'Pass "-v" for more info' not in \ + self.mock_display.notification.call_args[0][0] + assert f"http://{authzrs[0].body.identifier.value}/.well-known/acme-challenge/" + \ + b64encode(authzrs[0].body.challenges[0].chall.token).decode() in \ + self.mock_display.notification.call_args[0][0] + assert b64encode(account_key_thumbprint).decode() in \ + self.mock_display.notification.call_args[0][0] + assert f"_acme-challenge.{authzrs[1].body.identifier.value}" in \ + self.mock_display.notification.call_args[0][0] + assert authzrs[1].body.challenges[0].validation(self.mock_account.key) in \ + self.mock_display.notification.call_args[0][0] def test_perform_failure(self): authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)] @@ -212,9 +209,8 @@ class HandleAuthorizationsTest(unittest.TestCase): self.mock_auth.perform.side_effect = errors.AuthorizationError - self.assertRaises( - errors.AuthorizationError, self.handler.handle_authorizations, - mock_order, self.mock_config) + with pytest.raises(errors.AuthorizationError): + self.handler.handle_authorizations(mock_order, self.mock_config) def test_max_retries_exceeded(self): authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)] @@ -223,10 +219,10 @@ class HandleAuthorizationsTest(unittest.TestCase): # We will return STATUS_PENDING twice before returning STATUS_VALID. self.mock_net.poll.side_effect = _gen_mock_on_poll(retry=2) - with self.assertRaises(errors.AuthorizationError) as error: + with pytest.raises(errors.AuthorizationError, + match='All authorizations were not finalized by the CA.'): # We retry only once, so retries will be exhausted before STATUS_VALID is returned. self.handler.handle_authorizations(mock_order, self.mock_config, False, 1) - self.assertIn('All authorizations were not finalized by the CA.', str(error.exception)) @mock.patch('certbot._internal.auth_handler.time.sleep') def test_deadline_exceeded(self, mock_sleep): @@ -248,23 +244,23 @@ class HandleAuthorizationsTest(unittest.TestCase): self.mock_net.poll.side_effect = _gen_mock_on_poll(status=messages.STATUS_PENDING, wait_value=interval) - with self.assertRaises(errors.AuthorizationError) as error, \ - mock.patch('certbot._internal.auth_handler.datetime.datetime') as mock_dt: - mock_dt.now.side_effect = mock_now_effect - # Polling will only proceed for 30 minutes at most, so the second 20 minute sleep - # should be truncated and the polling should be aborted. - self.handler.handle_authorizations(mock_order, self.mock_config, False) - self.assertIn('All authorizations were not finalized by the CA.', str(error.exception)) + with pytest.raises(errors.AuthorizationError, + match='All authorizations were not finalized by the CA.'): + with mock.patch('certbot._internal.auth_handler.datetime.datetime') as mock_dt: + mock_dt.now.side_effect = mock_now_effect + # Polling will only proceed for 30 minutes at most, so the second 20 minute sleep + # should be truncated and the polling should be aborted. + self.handler.handle_authorizations(mock_order, self.mock_config, False) - self.assertEqual(mock_sleep.call_count, 3) # 1s, 20m and 10m sleep - self.assertEqual(mock_sleep.call_args_list[0][0][0], 1) - self.assertAlmostEqual(mock_sleep.call_args_list[1][0][0], interval - 1, delta=1) - self.assertAlmostEqual(mock_sleep.call_args_list[2][0][0], interval/2 - 1, delta=1) + assert mock_sleep.call_count == 3 # 1s, 20m and 10m sleep + assert mock_sleep.call_args_list[0][0][0] == 1 + assert abs(mock_sleep.call_args_list[1][0][0] - (interval - 1)) <= 1 + assert abs(mock_sleep.call_args_list[2][0][0] - (interval/2 - 1)) <= 1 def test_no_domains(self): mock_order = mock.MagicMock(authorizations=[]) - self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations, - mock_order, self.mock_config) + with pytest.raises(errors.AuthorizationError): + self.handler.handle_authorizations(mock_order, self.mock_config) def test_preferred_challenge_choice_common_acme_2(self): authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)] @@ -278,36 +274,32 @@ class HandleAuthorizationsTest(unittest.TestCase): self.mock_net.poll.side_effect = _gen_mock_on_poll() self.handler.handle_authorizations(mock_order, self.mock_config) - self.assertEqual(self.mock_auth.cleanup.call_count, 1) - self.assertEqual( - self.mock_auth.cleanup.call_args[0][0][0].typ, "http-01") + assert self.mock_auth.cleanup.call_count == 1 + assert self.mock_auth.cleanup.call_args[0][0][0].typ == "http-01" def test_preferred_challenges_not_supported_acme_2(self): authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)] mock_order = mock.MagicMock(authorizations=authzrs) self.handler.pref_challs.append(challenges.DNS01.typ) - self.assertRaises( - errors.AuthorizationError, self.handler.handle_authorizations, - mock_order, self.mock_config) + with pytest.raises(errors.AuthorizationError): + self.handler.handle_authorizations(mock_order, self.mock_config) def test_dns_only_challenge_not_supported(self): authzrs = [gen_dom_authzr(domain="0", challs=[acme_util.DNS01])] mock_order = mock.MagicMock(authorizations=authzrs) - self.assertRaises( - errors.AuthorizationError, self.handler.handle_authorizations, - mock_order, self.mock_config) + with pytest.raises(errors.AuthorizationError): + self.handler.handle_authorizations(mock_order, self.mock_config) def test_perform_error(self): self.mock_auth.perform.side_effect = errors.AuthorizationError authzr = gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES) mock_order = mock.MagicMock(authorizations=[authzr]) - self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations, - mock_order, self.mock_config) + with pytest.raises(errors.AuthorizationError): + self.handler.handle_authorizations(mock_order, self.mock_config) - self.assertEqual(self.mock_auth.cleanup.call_count, 1) - self.assertEqual( - self.mock_auth.cleanup.call_args[0][0][0].typ, "http-01") + assert self.mock_auth.cleanup.call_count == 1 + assert self.mock_auth.cleanup.call_args[0][0][0].typ == "http-01" def test_answer_error(self): self.mock_net.answer_challenge.side_effect = errors.AuthorizationError @@ -315,12 +307,10 @@ class HandleAuthorizationsTest(unittest.TestCase): authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)] mock_order = mock.MagicMock(authorizations=authzrs) - self.assertRaises( - errors.AuthorizationError, self.handler.handle_authorizations, - mock_order, self.mock_config) - self.assertEqual(self.mock_auth.cleanup.call_count, 1) - self.assertEqual( - self.mock_auth.cleanup.call_args[0][0][0].typ, "http-01") + with pytest.raises(errors.AuthorizationError): + self.handler.handle_authorizations(mock_order, self.mock_config) + assert self.mock_auth.cleanup.call_count == 1 + assert self.mock_auth.cleanup.call_args[0][0][0].typ == "http-01" def test_incomplete_authzr_error(self): authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)] @@ -328,12 +318,10 @@ class HandleAuthorizationsTest(unittest.TestCase): self.mock_net.poll.side_effect = _gen_mock_on_poll(status=messages.STATUS_INVALID) with test_util.patch_display_util(): - with self.assertRaises(errors.AuthorizationError) as error: + with pytest.raises(errors.AuthorizationError, match='Some challenges have failed.'): self.handler.handle_authorizations(mock_order, self.mock_config, False) - self.assertIn('Some challenges have failed.', str(error.exception)) - self.assertEqual(self.mock_auth.cleanup.call_count, 1) - self.assertEqual( - self.mock_auth.cleanup.call_args[0][0][0].typ, "http-01") + assert self.mock_auth.cleanup.call_count == 1 + assert self.mock_auth.cleanup.call_args[0][0][0].typ == "http-01" def test_best_effort(self): def _conditional_mock_on_poll(authzr): @@ -357,18 +345,16 @@ class HandleAuthorizationsTest(unittest.TestCase): valid_authzr = self.handler.handle_authorizations(mock_order, self.mock_config, True) # Because best_effort=True, we did not blow up. Instead ... - self.assertEqual(len(valid_authzr), 1) # ... the valid authzr has been processed - self.assertEqual(mock_report.call_count, 1) # ... the invalid authzr has been reported + assert len(valid_authzr) == 1 # ... the valid authzr has been processed + assert mock_report.call_count == 1 # ... the invalid authzr has been reported self.mock_net.poll.side_effect = _gen_mock_on_poll(status=messages.STATUS_INVALID) with test_util.patch_display_util(): - with self.assertRaises(errors.AuthorizationError) as error: + with pytest.raises(errors.AuthorizationError, match='All challenges have failed.'): + # Despite best_effort=True, process will fail because no authzr is valid. self.handler.handle_authorizations(mock_order, self.mock_config, True) - # Despite best_effort=True, process will fail because no authzr is valid. - self.assertIn('All challenges have failed.', str(error.exception)) - def test_validated_challenge_not_rerun(self): # With a pending challenge that is not supported by the plugin, we # expect an exception to be raised. @@ -377,9 +363,8 @@ class HandleAuthorizationsTest(unittest.TestCase): [acme_util.DNS01], [messages.STATUS_PENDING]) mock_order = mock.MagicMock(authorizations=[authzr]) - self.assertRaises( - errors.AuthorizationError, self.handler.handle_authorizations, - mock_order, self.mock_config) + with pytest.raises(errors.AuthorizationError): + self.handler.handle_authorizations(mock_order, self.mock_config) # With a validated challenge that is not supported by the plugin, we # expect the challenge to not be solved again and @@ -416,13 +401,13 @@ class HandleAuthorizationsTest(unittest.TestCase): authzrs, failed = self.handler.deactivate_valid_authorizations(orderr) - self.assertEqual(self.mock_net.deactivate_authorization.call_count, 2) - self.assertEqual(len(authzrs), 1) - self.assertEqual(len(failed), 1) - self.assertEqual(authzrs[0].body.identifier.value, "is_valid") - self.assertEqual(authzrs[0].body.status, messages.STATUS_DEACTIVATED) - self.assertEqual(failed[0].body.identifier.value, "is_valid_but_will_fail") - self.assertEqual(failed[0].body.status, messages.STATUS_VALID) + assert self.mock_net.deactivate_authorization.call_count == 2 + assert len(authzrs) == 1 + assert len(failed) == 1 + assert authzrs[0].body.identifier.value == "is_valid" + assert authzrs[0].body.status == messages.STATUS_DEACTIVATED + assert failed[0].body.identifier.value == "is_valid_but_will_fail" + assert failed[0].body.status == messages.STATUS_VALID def _gen_mock_on_poll(status=messages.STATUS_VALID, retry=0, wait_value=1): @@ -448,12 +433,10 @@ class ChallbToAchallTest(unittest.TestCase): return challb_to_achall(challb, "account_key", "domain") def test_it(self): - self.assertEqual( - self._call(acme_util.HTTP01_P), + assert self._call(acme_util.HTTP01_P) == \ achallenges.KeyAuthorizationAnnotatedChallenge( challb=acme_util.HTTP01_P, account_key="account_key", - domain="domain"), - ) + domain="domain") class GenChallengePathTest(unittest.TestCase): @@ -476,16 +459,16 @@ class GenChallengePathTest(unittest.TestCase): challbs = (acme_util.DNS01_P, acme_util.HTTP01_P) prefs = [challenges.DNS01, challenges.HTTP01] - self.assertEqual(self._call(challbs, prefs), (0,)) - self.assertEqual(self._call(challbs[::-1], prefs), (1,)) + assert self._call(challbs, prefs) == (0,) + assert self._call(challbs[::-1], prefs) == (1,) def test_not_supported(self): challbs = (acme_util.DNS01_P,) prefs = [challenges.HTTP01] # smart path fails because no challs in prefs satisfies combos - self.assertRaises( - errors.AuthorizationError, self._call, challbs, prefs) + with pytest.raises(errors.AuthorizationError): + self._call(challbs, prefs) class ReportFailedAuthzrsTest(unittest.TestCase): @@ -509,7 +492,7 @@ class ReportFailedAuthzrsTest(unittest.TestCase): } # Prevent future regressions if the error type changes - self.assertIsNotNone(kwargs["error"].description) + assert kwargs["error"].description is not None http_01 = messages.ChallengeBody(**kwargs) @@ -577,7 +560,7 @@ class ReportFailedAuthzrsTest(unittest.TestCase): self.mock_auth.auth_hint.side_effect = Exception self.handler = AuthHandler(self.mock_auth, mock.MagicMock(), mock.MagicMock(), []) self.handler._report_failed_authzrs([self.authzr1]) - self.assertEqual(mock_notify.call_count, 1) + assert mock_notify.call_count == 1 def gen_auth_resp(chall_list): diff --git a/certbot/tests/cert_manager_test.py b/certbot/tests/cert_manager_test.py index 659a6fc47..caacc520f 100644 --- a/certbot/tests/cert_manager_test.py +++ b/certbot/tests/cert_manager_test.py @@ -97,9 +97,8 @@ class UpdateLiveSymlinksTest(BaseCertManagerTest): for domain in self.domains: for kind in ALL_FOUR: os.chdir(os.path.dirname(self.config_files[domain][kind])) - self.assertEqual( - filesystem.realpath(filesystem.readlink(self.config_files[domain][kind])), - filesystem.realpath(archive_paths[domain][kind])) + assert filesystem.realpath(filesystem.readlink(self.config_files[domain][kind])) == \ + filesystem.realpath(archive_paths[domain][kind]) finally: os.chdir(prev_dir) @@ -138,7 +137,7 @@ class DeleteTest(storage_test.BaseRenewableCertTest): mock_util().yesno.return_value = False self.config.certname = "example.org" self._call() - self.assertEqual(mock_delete_files.call_count, 0) + assert mock_delete_files.call_count == 0 @test_util.patch_display_util() @mock.patch('certbot._internal.cert_manager.lineage_for_certname') @@ -162,7 +161,7 @@ class DeleteTest(storage_test.BaseRenewableCertTest): mock_util().checklist.return_value = (display_util.OK, ["example.org"]) mock_util().yesno.return_value = False self._call() - self.assertEqual(mock_delete_files.call_count, 0) + assert mock_delete_files.call_count == 0 @test_util.patch_display_util() @mock.patch('certbot._internal.cert_manager.lineage_for_certname') @@ -176,7 +175,7 @@ class DeleteTest(storage_test.BaseRenewableCertTest): self._call() mock_delete_files.assert_any_call(self.config, "example.org") mock_delete_files.assert_any_call(self.config, "other.org") - self.assertEqual(mock_delete_files.call_count, 2) + assert mock_delete_files.call_count == 2 @test_util.patch_display_util() @mock.patch('certbot._internal.cert_manager.lineage_for_certname') @@ -188,7 +187,7 @@ class DeleteTest(storage_test.BaseRenewableCertTest): mock_util().checklist.return_value = (display_util.OK, ["example.org", "other.org"]) mock_util().yesno.return_value = False self._call() - self.assertEqual(mock_delete_files.call_count, 0) + assert mock_delete_files.call_count == 0 class CertificatesTest(BaseCertManagerTest): @@ -202,16 +201,16 @@ class CertificatesTest(BaseCertManagerTest): @test_util.patch_display_util() def test_certificates_parse_fail(self, mock_utility, mock_logger): self._certificates(self.config) - self.assertTrue(mock_logger.warning.called) #pylint: disable=no-member - self.assertTrue(mock_utility.called) + assert mock_logger.warning.called #pylint: disable=no-member + assert mock_utility.called @mock.patch('certbot._internal.cert_manager.logger') @test_util.patch_display_util() def test_certificates_quiet(self, mock_utility, mock_logger): self.config.quiet = True self._certificates(self.config) - self.assertIs(mock_utility.notification.called, False) - self.assertTrue(mock_logger.warning.called) #pylint: disable=no-member + assert mock_utility.notification.called is False + assert mock_logger.warning.called #pylint: disable=no-member @mock.patch('certbot.crypto_util.verify_renewable_cert') @mock.patch('certbot._internal.cert_manager.logger') @@ -223,10 +222,10 @@ class CertificatesTest(BaseCertManagerTest): mock_verifier.return_value = None mock_report.return_value = "" self._certificates(self.config) - self.assertIs(mock_logger.warning.called, False) - self.assertTrue(mock_report.called) - self.assertTrue(mock_utility.called) - self.assertTrue(mock_renewable_cert.called) + assert mock_logger.warning.called is False + assert mock_report.called + assert mock_utility.called + assert mock_renewable_cert.called @mock.patch('certbot._internal.cert_manager.logger') @test_util.patch_display_util() @@ -241,8 +240,8 @@ class CertificatesTest(BaseCertManagerTest): filesystem.makedirs(empty_config.renewal_configs_dir) self._certificates(empty_config) - self.assertIs(mock_logger.warning.called, False) - self.assertTrue(mock_utility.called) + assert mock_logger.warning.called is False + assert mock_utility.called shutil.rmtree(empty_tempdir) @mock.patch('certbot.crypto_util.get_serial_from_cert') @@ -270,34 +269,34 @@ class CertificatesTest(BaseCertManagerTest): get_report = lambda: cert_manager._report_human_readable(mock_config, parsed_certs) out = get_report() - self.assertIn("INVALID: EXPIRED", out) + assert "INVALID: EXPIRED" in out cert.target_expiry += datetime.timedelta(hours=2) # pylint: disable=protected-access out = get_report() - self.assertIs('1 hour' in out or '2 hour(s)' in out, True) - self.assertIn('VALID', out) - self.assertNotIn('INVALID', out) + assert ('1 hour' in out or '2 hour(s)' in out) is True + assert 'VALID' in out + assert 'INVALID' not in out cert.target_expiry += datetime.timedelta(days=1) # pylint: disable=protected-access out = get_report() - self.assertIn('1 day', out) - self.assertNotIn('under', out) - self.assertIn('VALID', out) - self.assertNotIn('INVALID', out) + assert '1 day' in out + assert 'under' not in out + assert 'VALID' in out + assert 'INVALID' not in out cert.target_expiry += datetime.timedelta(days=2) # pylint: disable=protected-access out = get_report() - self.assertIn('3 days', out) - self.assertIn('VALID', out) - self.assertNotIn('INVALID', out) + assert '3 days' in out + assert 'VALID' in out + assert 'INVALID' not in out cert.is_test_cert = True mock_revoked.return_value = True out = get_report() - self.assertIn('INVALID: TEST_CERT, REVOKED', out) + assert 'INVALID: TEST_CERT, REVOKED' in out cert = mock.MagicMock(lineagename="indescribable") cert.target_expiry = expiry @@ -306,19 +305,19 @@ class CertificatesTest(BaseCertManagerTest): parsed_certs.append(cert) out = get_report() - self.assertEqual(len(re.findall("INVALID:", out)), 2) + assert len(re.findall("INVALID:", out)) == 2 mock_config.domains = ["thrice.named"] out = get_report() - self.assertEqual(len(re.findall("INVALID:", out)), 1) + assert len(re.findall("INVALID:", out)) == 1 mock_config.domains = ["nameone"] out = get_report() - self.assertEqual(len(re.findall("INVALID:", out)), 2) + assert len(re.findall("INVALID:", out)) == 2 mock_config.certname = "indescribable" out = get_report() - self.assertEqual(len(re.findall("INVALID:", out)), 1) + assert len(re.findall("INVALID:", out)) == 1 mock_config.certname = "horror" out = get_report() - self.assertEqual(len(re.findall("INVALID:", out)), 0) + assert len(re.findall("INVALID:", out)) == 0 class SearchLineagesTest(BaseCertManagerTest): @@ -334,8 +333,8 @@ class SearchLineagesTest(BaseCertManagerTest): from certbot._internal import cert_manager # pylint: disable=protected-access - self.assertEqual(cert_manager._search_lineages(self.config, lambda x: x, "check"), "check") - self.assertTrue(mock_make_or_verify_dir.called) + assert cert_manager._search_lineages(self.config, lambda x: x, "check") == "check" + assert mock_make_or_verify_dir.called class LineageForCertnameTest(BaseCertManagerTest): @@ -350,24 +349,24 @@ class LineageForCertnameTest(BaseCertManagerTest): mock_match = mock.Mock(lineagename="example.com") mock_renewable_cert.return_value = mock_match from certbot._internal import cert_manager - self.assertEqual(cert_manager.lineage_for_certname(self.config, "example.com"), mock_match) - self.assertTrue(mock_make_or_verify_dir.called) + assert cert_manager.lineage_for_certname(self.config, "example.com") == mock_match + assert mock_make_or_verify_dir.called @mock.patch('certbot.util.make_or_verify_dir') @mock.patch('certbot._internal.storage.renewal_file_for_certname') def test_no_match(self, mock_renewal_conf_file, mock_make_or_verify_dir): mock_renewal_conf_file.return_value = "other.com.conf" from certbot._internal import cert_manager - self.assertIsNone(cert_manager.lineage_for_certname(self.config, "example.com")) - self.assertTrue(mock_make_or_verify_dir.called) + assert cert_manager.lineage_for_certname(self.config, "example.com") is None + assert mock_make_or_verify_dir.called @mock.patch('certbot.util.make_or_verify_dir') @mock.patch('certbot._internal.storage.renewal_file_for_certname') def test_no_renewal_file(self, mock_renewal_conf_file, mock_make_or_verify_dir): mock_renewal_conf_file.side_effect = errors.CertStorageError() from certbot._internal import cert_manager - self.assertIsNone(cert_manager.lineage_for_certname(self.config, "example.com")) - self.assertTrue(mock_make_or_verify_dir.called) + assert cert_manager.lineage_for_certname(self.config, "example.com") is None + assert mock_make_or_verify_dir.called class DomainsForCertnameTest(BaseCertManagerTest): @@ -384,17 +383,17 @@ class DomainsForCertnameTest(BaseCertManagerTest): mock_match.names.return_value = domains mock_renewable_cert.return_value = mock_match from certbot._internal import cert_manager - self.assertEqual(cert_manager.domains_for_certname(self.config, "example.com"), - domains) - self.assertTrue(mock_make_or_verify_dir.called) + assert cert_manager.domains_for_certname(self.config, "example.com") == \ + domains + assert mock_make_or_verify_dir.called @mock.patch('certbot.util.make_or_verify_dir') @mock.patch('certbot._internal.storage.renewal_file_for_certname') def test_no_match(self, mock_renewal_conf_file, mock_make_or_verify_dir): mock_renewal_conf_file.return_value = "somefile.conf" from certbot._internal import cert_manager - self.assertIsNone(cert_manager.domains_for_certname(self.config, "other.com")) - self.assertTrue(mock_make_or_verify_dir.called) + assert cert_manager.domains_for_certname(self.config, "other.com") is None + assert mock_make_or_verify_dir.called class RenameLineageTest(BaseCertManagerTest): @@ -417,15 +416,18 @@ class RenameLineageTest(BaseCertManagerTest): # if not choices mock_renewal_conf_files.return_value = [] - self.assertRaises(errors.Error, self._call, self.config) + with pytest.raises(errors.Error): + self._call(self.config) mock_renewal_conf_files.return_value = ["one.conf"] util_mock = mock_get_utility() util_mock.menu.return_value = (display_util.CANCEL, 0) - self.assertRaises(errors.Error, self._call, self.config) + with pytest.raises(errors.Error): + self._call(self.config) util_mock.menu.return_value = (display_util.OK, -1) - self.assertRaises(errors.Error, self._call, self.config) + with pytest.raises(errors.Error): + self._call(self.config) @test_util.patch_display_util() def test_no_new_certname(self, mock_get_utility): @@ -434,10 +436,12 @@ class RenameLineageTest(BaseCertManagerTest): util_mock = mock_get_utility() util_mock.input.return_value = (display_util.CANCEL, "name") - self.assertRaises(errors.Error, self._call, self.config) + with pytest.raises(errors.Error): + self._call(self.config) util_mock.input.return_value = (display_util.OK, None) - self.assertRaises(errors.Error, self._call, self.config) + with pytest.raises(errors.Error): + self._call(self.config) @test_util.patch_display_util() @mock.patch('certbot._internal.cert_manager.lineage_for_certname') @@ -445,8 +449,8 @@ class RenameLineageTest(BaseCertManagerTest): self.config.certname = "one" self.config.new_certname = "two" mock_lineage_for_certname.return_value = None - self.assertRaises(errors.ConfigurationError, - self._call, self.config) + with pytest.raises(errors.ConfigurationError): + self._call(self.config) @test_util.patch_display_util() @mock.patch("certbot._internal.storage.RenewableCert._check_symlinks") @@ -455,8 +459,8 @@ class RenameLineageTest(BaseCertManagerTest): self._call(self.config) from certbot._internal import cert_manager updated_lineage = cert_manager.lineage_for_certname(self.config, self.config.new_certname) - self.assertIsNotNone(updated_lineage) - self.assertEqual(updated_lineage.lineagename, self.config.new_certname) + assert updated_lineage is not None + assert updated_lineage.lineagename == self.config.new_certname @test_util.patch_display_util() @mock.patch("certbot._internal.storage.RenewableCert._check_symlinks") @@ -468,8 +472,8 @@ class RenameLineageTest(BaseCertManagerTest): self._call(self.config) from certbot._internal import cert_manager updated_lineage = cert_manager.lineage_for_certname(self.config, self.config.new_certname) - self.assertIsNotNone(updated_lineage) - self.assertEqual(updated_lineage.lineagename, self.config.new_certname) + assert updated_lineage is not None + assert updated_lineage.lineagename == self.config.new_certname @test_util.patch_display_util() @mock.patch("certbot._internal.storage.RenewableCert._check_symlinks") @@ -478,10 +482,12 @@ class RenameLineageTest(BaseCertManagerTest): # for example, don't rename to existing certname self.config.new_certname = "example.org" - self.assertRaises(errors.ConfigurationError, self._call, self.config) + with pytest.raises(errors.ConfigurationError): + self._call(self.config) self.config.new_certname = "one{0}two".format(os.path.sep) - self.assertRaises(errors.ConfigurationError, self._call, self.config) + with pytest.raises(errors.ConfigurationError): + self._call(self.config) class DuplicativeCertsTest(storage_test.BaseRenewableCertTest): @@ -502,24 +508,24 @@ class DuplicativeCertsTest(storage_test.BaseRenewableCertTest): # No overlap at all result = find_duplicative_certs( self.config, ['wow.net', 'hooray.org']) - self.assertEqual(result, (None, None)) + assert result == (None, None) # Totally identical result = find_duplicative_certs( self.config, ['example.com', 'www.example.com']) - self.assertTrue(result[0].configfile.filename.endswith('example.org.conf')) - self.assertIsNone(result[1]) + assert result[0].configfile.filename.endswith('example.org.conf') + assert result[1] is None # Superset result = find_duplicative_certs( self.config, ['example.com', 'www.example.com', 'something.new']) - self.assertIsNone(result[0]) - self.assertTrue(result[1].configfile.filename.endswith('example.org.conf')) + assert result[0] is None + assert result[1].configfile.filename.endswith('example.org.conf') # Partial overlap doesn't count result = find_duplicative_certs( self.config, ['example.com', 'something.new']) - self.assertEqual(result, (None, None)) + assert result == (None, None) class CertPathToLineageTest(storage_test.BaseRenewableCertTest): @@ -542,19 +548,20 @@ class CertPathToLineageTest(storage_test.BaseRenewableCertTest): return _archive_files(cli_config, filetype) def test_basic_match(self): - self.assertEqual('example.org', self._call(self.config)) + assert 'example.org' == self._call(self.config) def test_no_match_exists(self): bad_test_config = self.config bad_test_config.cert_path = os.path.join(self.config.config_dir, 'live', 'SailorMoon', 'fullchain.pem') - self.assertRaises(errors.Error, self._call, bad_test_config) + with pytest.raises(errors.Error): + self._call(bad_test_config) @mock.patch('certbot._internal.cert_manager._acceptable_matches') def test_options_fullchain(self, mock_acceptable_matches): mock_acceptable_matches.return_value = [lambda x: x.fullchain_path] self.config.fullchain_path = self.fullchain - self.assertEqual('example.org', self._call(self.config)) + assert 'example.org' == self._call(self.config) @mock.patch('certbot._internal.cert_manager._acceptable_matches') def test_options_cert_path(self, mock_acceptable_matches): @@ -562,7 +569,7 @@ class CertPathToLineageTest(storage_test.BaseRenewableCertTest): test_cert_path = os.path.join(self.config.config_dir, 'live', 'example.org', 'cert.pem') self.config.cert_path = test_cert_path - self.assertEqual('example.org', self._call(self.config)) + assert 'example.org' == self._call(self.config) @mock.patch('certbot._internal.cert_manager._acceptable_matches') def test_options_archive_cert(self, mock_acceptable_matches): @@ -570,7 +577,7 @@ class CertPathToLineageTest(storage_test.BaseRenewableCertTest): self.config.cert_path = os.path.join(self.config.config_dir, 'archive', 'example.org', 'cert11.pem') mock_acceptable_matches.return_value = [lambda x: self._archive_files(x, 'cert')] - self.assertEqual('example.org', self._call(self.config)) + assert 'example.org' == self._call(self.config) @mock.patch('certbot._internal.cert_manager._acceptable_matches') def test_options_archive_fullchain(self, mock_acceptable_matches): @@ -578,11 +585,11 @@ class CertPathToLineageTest(storage_test.BaseRenewableCertTest): 'example.org', 'fullchain11.pem') mock_acceptable_matches.return_value = [lambda x: self._archive_files(x, 'fullchain')] - self.assertEqual('example.org', self._call(self.config)) + assert 'example.org' == self._call(self.config) def test_only_path(self): self.config.cert_path = self.fullchain - self.assertEqual('example.org', self._call(self.config)) + assert 'example.org' == self._call(self.config) class MatchAndCheckOverlaps(storage_test.BaseRenewableCertTest): @@ -603,18 +610,20 @@ class MatchAndCheckOverlaps(storage_test.BaseRenewableCertTest): def test_basic_match(self): from certbot._internal.cert_manager import _acceptable_matches - self.assertEqual(['example.org'], self._call(self.config, _acceptable_matches(), - lambda x: self.config.cert_path, lambda x: x.lineagename)) + assert ['example.org'] == self._call(self.config, _acceptable_matches(), + lambda x: self.config.cert_path, lambda x: x.lineagename) @mock.patch('certbot._internal.cert_manager._search_lineages') def test_no_matches(self, mock_search_lineages): mock_search_lineages.return_value = [] - self.assertRaises(errors.Error, self._call, self.config, None, None, None) + with pytest.raises(errors.Error): + self._call(self.config, None, None, None) @mock.patch('certbot._internal.cert_manager._search_lineages') def test_too_many_matches(self, mock_search_lineages): mock_search_lineages.return_value = ['spider', 'dance'] - self.assertRaises(errors.OverlappingMatchFound, self._call, self.config, None, None, None) + with pytest.raises(errors.OverlappingMatchFound): + self._call(self.config, None, None, None) class GetCertnameTest(unittest.TestCase): @@ -635,10 +644,9 @@ class GetCertnameTest(unittest.TestCase): from certbot._internal import cert_manager prompt = "Which certificate would you" self.mock_get_utility().menu.return_value = (display_util.OK, 0) - self.assertEqual( - cert_manager.get_certnames( - self.config, "verb", allow_multiple=False), ['example.com']) - self.assertIn(prompt, self.mock_get_utility().menu.call_args[0][0]) + assert cert_manager.get_certnames( + self.config, "verb", allow_multiple=False) == ['example.com'] + assert prompt in self.mock_get_utility().menu.call_args[0][0] @mock.patch('certbot._internal.storage.renewal_conf_files') @mock.patch('certbot._internal.storage.lineagename_for_filename') @@ -648,12 +656,11 @@ class GetCertnameTest(unittest.TestCase): from certbot._internal import cert_manager prompt = "custom prompt" self.mock_get_utility().menu.return_value = (display_util.OK, 0) - self.assertEqual( - cert_manager.get_certnames( - self.config, "verb", allow_multiple=False, custom_prompt=prompt), - ['example.com']) - self.assertEqual(self.mock_get_utility().menu.call_args[0][0], - prompt) + assert cert_manager.get_certnames( + self.config, "verb", allow_multiple=False, custom_prompt=prompt) == \ + ['example.com'] + assert self.mock_get_utility().menu.call_args[0][0] == \ + prompt @mock.patch('certbot._internal.storage.renewal_conf_files') @mock.patch('certbot._internal.storage.lineagename_for_filename') @@ -662,10 +669,8 @@ class GetCertnameTest(unittest.TestCase): mock_name.return_value = 'example.com' from certbot._internal import cert_manager self.mock_get_utility().menu.return_value = (display_util.CANCEL, 0) - self.assertRaises( - errors.Error, - cert_manager.get_certnames, - self.config, "erroring_anyway", allow_multiple=False) + with pytest.raises(errors.Error): + cert_manager.get_certnames(self.config, "erroring_anyway", allow_multiple=False) @mock.patch('certbot._internal.storage.renewal_conf_files') @mock.patch('certbot._internal.storage.lineagename_for_filename') @@ -676,10 +681,9 @@ class GetCertnameTest(unittest.TestCase): prompt = "Which certificate(s) would you" self.mock_get_utility().checklist.return_value = (display_util.OK, ['example.com']) - self.assertEqual( - cert_manager.get_certnames( - self.config, "verb", allow_multiple=True), ['example.com']) - self.assertIn(prompt, self.mock_get_utility().checklist.call_args[0][0]) + assert cert_manager.get_certnames( + self.config, "verb", allow_multiple=True) == ['example.com'] + assert prompt in self.mock_get_utility().checklist.call_args[0][0] @mock.patch('certbot._internal.storage.renewal_conf_files') @mock.patch('certbot._internal.storage.lineagename_for_filename') @@ -690,13 +694,11 @@ class GetCertnameTest(unittest.TestCase): prompt = "custom prompt" self.mock_get_utility().checklist.return_value = (display_util.OK, ['example.com']) - self.assertEqual( - cert_manager.get_certnames( - self.config, "verb", allow_multiple=True, custom_prompt=prompt), - ['example.com']) - self.assertEqual( - self.mock_get_utility().checklist.call_args[0][0], - prompt) + assert cert_manager.get_certnames( + self.config, "verb", allow_multiple=True, custom_prompt=prompt) == \ + ['example.com'] + assert self.mock_get_utility().checklist.call_args[0][0] == \ + prompt @mock.patch('certbot._internal.storage.renewal_conf_files') @mock.patch('certbot._internal.storage.lineagename_for_filename') @@ -705,10 +707,8 @@ class GetCertnameTest(unittest.TestCase): mock_name.return_value = 'example.com' from certbot._internal import cert_manager self.mock_get_utility().checklist.return_value = (display_util.CANCEL, []) - self.assertRaises( - errors.Error, - cert_manager.get_certnames, - self.config, "erroring_anyway", allow_multiple=True) + with pytest.raises(errors.Error): + cert_manager.get_certnames(self.config, "erroring_anyway", allow_multiple=True) if __name__ == "__main__": diff --git a/certbot/tests/cli_test.py b/certbot/tests/cli_test.py index 53eb2a5bc..16e1f7d75 100644 --- a/certbot/tests/cli_test.py +++ b/certbot/tests/cli_test.py @@ -41,16 +41,16 @@ class TestReadFile(TempDirTestCase): # POSIX systems. real_path = filesystem.realpath(os.path.join(self.tempdir, 'foo')) relative_path = os.path.relpath(real_path) - self.assertRaises( - argparse.ArgumentTypeError, cli.read_file, relative_path) + with pytest.raises(argparse.ArgumentTypeError): + cli.read_file(relative_path) test_contents = b'bar\n' with open(relative_path, 'wb') as f: f.write(test_contents) path, contents = cli.read_file(relative_path) - self.assertEqual(path, os.path.abspath(path)) - self.assertEqual(contents, test_contents) + assert path == os.path.abspath(path) + assert contents == test_contents finally: os.chdir(curr_dir) @@ -60,13 +60,13 @@ class FlagDefaultTest(unittest.TestCase): def test_default_directories(self): if os.name != 'nt': - self.assertEqual(cli.flag_default('config_dir'), '/etc/letsencrypt') - self.assertEqual(cli.flag_default('work_dir'), '/var/lib/letsencrypt') - self.assertEqual(cli.flag_default('logs_dir'), '/var/log/letsencrypt') + assert cli.flag_default('config_dir') == '/etc/letsencrypt' + assert cli.flag_default('work_dir') == '/var/lib/letsencrypt' + assert cli.flag_default('logs_dir') == '/var/log/letsencrypt' else: - self.assertEqual(cli.flag_default('config_dir'), 'C:\\Certbot') - self.assertEqual(cli.flag_default('work_dir'), 'C:\\Certbot\\lib') - self.assertEqual(cli.flag_default('logs_dir'), 'C:\\Certbot\\log') + assert cli.flag_default('config_dir') == 'C:\\Certbot' + assert cli.flag_default('work_dir') == 'C:\\Certbot\\lib' + assert cli.flag_default('logs_dir') == 'C:\\Certbot\\log' class ParseTest(unittest.TestCase): @@ -99,7 +99,8 @@ class ParseTest(unittest.TestCase): with test_util.patch_display_util() as mock_get_utility: mock_get_utility().notification.side_effect = write_msg with mock.patch('certbot._internal.main.sys.stderr'): - self.assertRaises(SystemExit, self._unmocked_parse, args, output) + with pytest.raises(SystemExit): + self._unmocked_parse(args, output) return output.getvalue() @@ -116,18 +117,18 @@ class ParseTest(unittest.TestCase): mock_flag_default.side_effect = shim namespace = self.parse(["certonly"]) - self.assertEqual(namespace.domains, []) + assert namespace.domains == [] with open(tmp_config.name, 'w') as file_h: file_h.write("domains = example.com") namespace = self.parse(["certonly"]) - self.assertEqual(namespace.domains, ["example.com"]) + assert namespace.domains == ["example.com"] namespace = self.parse(["renew"]) - self.assertEqual(namespace.domains, []) + assert namespace.domains == [] def test_no_args(self): namespace = self.parse([]) for d in ('config_dir', 'logs_dir', 'work_dir'): - self.assertEqual(getattr(namespace, d), cli.flag_default(d)) + assert getattr(namespace, d) == cli.flag_default(d) def test_install_abspath(self): cert = 'cert' @@ -140,136 +141,137 @@ class ParseTest(unittest.TestCase): '--key-path', 'key', '--chain-path', 'chain', '--fullchain-path', 'fullchain']) - self.assertEqual(namespace.cert_path, os.path.abspath(cert)) - self.assertEqual(namespace.key_path, os.path.abspath(key)) - self.assertEqual(namespace.chain_path, os.path.abspath(chain)) - self.assertEqual(namespace.fullchain_path, os.path.abspath(fullchain)) + assert namespace.cert_path == os.path.abspath(cert) + assert namespace.key_path == os.path.abspath(key) + assert namespace.chain_path == os.path.abspath(chain) + assert namespace.fullchain_path == os.path.abspath(fullchain) def test_help(self): self._help_output(['--help']) # assert SystemExit is raised here out = self._help_output(['--help', 'all']) - self.assertIn("--configurator", out) - self.assertIn("how a certificate is deployed", out) - self.assertIn("--webroot-path", out) - self.assertNotIn("--text", out) - self.assertNotIn("%s", out) - self.assertNotIn("{0}", out) - self.assertNotIn("--renew-hook", out) + assert "--configurator" in out + assert "how a certificate is deployed" in out + assert "--webroot-path" in out + assert "--text" not in out + assert "%s" not in out + assert "{0}" not in out + assert "--renew-hook" not in out out = self._help_output(['-h', 'nginx']) if "nginx" in PLUGINS: # may be false while building distributions without plugins - self.assertIn("--nginx-ctl", out) - self.assertNotIn("--webroot-path", out) - self.assertNotIn("--checkpoints", out) + assert "--nginx-ctl" in out + assert "--webroot-path" not in out + assert "--checkpoints" not in out out = self._help_output(['-h']) if "nginx" in PLUGINS: - self.assertIn("Use the Nginx plugin", out) + assert "Use the Nginx plugin" in out else: - self.assertIn("(the certbot nginx plugin is not", out) + assert "(the certbot nginx plugin is not" in out out = self._help_output(['--help', 'plugins']) - self.assertNotIn("--webroot-path", out) - self.assertIn("--prepare", out) - self.assertIn('"plugins" subcommand', out) + assert "--webroot-path" not in out + assert "--prepare" in out + assert '"plugins" subcommand' in out # test multiple topics out = self._help_output(['-h', 'renew']) - self.assertIn("--keep", out) + assert "--keep" in out out = self._help_output(['-h', 'automation']) - self.assertIn("--keep", out) + assert "--keep" in out out = self._help_output(['-h', 'revoke']) - self.assertNotIn("--keep", out) + assert "--keep" not in out out = self._help_output(['--help', 'install']) - self.assertIn("--cert-path", out) - self.assertIn("--key-path", out) + assert "--cert-path" in out + assert "--key-path" in out out = self._help_output(['--help', 'revoke']) - self.assertIn("--cert-path", out) - self.assertIn("--key-path", out) - self.assertIn("--reason", out) - self.assertIn("--delete-after-revoke", out) - self.assertIn("--no-delete-after-revoke", out) + assert "--cert-path" in out + assert "--key-path" in out + assert "--reason" in out + assert "--delete-after-revoke" in out + assert "--no-delete-after-revoke" in out out = self._help_output(['-h', 'register']) - self.assertNotIn("--cert-path", out) - self.assertNotIn("--key-path", out) + assert "--cert-path" not in out + assert "--key-path" not in out out = self._help_output(['-h']) - self.assertIn(cli.SHORT_USAGE, out) - self.assertIn(cli.COMMAND_OVERVIEW[:100], out) - self.assertNotIn("%s", out) - self.assertNotIn("{0}", out) + assert cli.SHORT_USAGE in out + assert cli.COMMAND_OVERVIEW[:100] in out + assert "%s" not in out + assert "{0}" not in out def test_help_no_dashes(self): self._help_output(['help']) # assert SystemExit is raised here out = self._help_output(['help', 'all']) - self.assertIn("--configurator", out) - self.assertIn("how a certificate is deployed", out) - self.assertIn("--webroot-path", out) - self.assertNotIn("--text", out) - self.assertNotIn("%s", out) - self.assertNotIn("{0}", out) + assert "--configurator" in out + assert "how a certificate is deployed" in out + assert "--webroot-path" in out + assert "--text" not in out + assert "%s" not in out + assert "{0}" not in out out = self._help_output(['help', 'install']) - self.assertIn("--cert-path", out) - self.assertIn("--key-path", out) + assert "--cert-path" in out + assert "--key-path" in out out = self._help_output(['help', 'revoke']) - self.assertIn("--cert-path", out) - self.assertIn("--key-path", out) + assert "--cert-path" in out + assert "--key-path" in out def test_parse_domains(self): short_args = ['-d', 'example.com'] namespace = self.parse(short_args) - self.assertEqual(namespace.domains, ['example.com']) + assert namespace.domains == ['example.com'] short_args = ['-d', 'trailing.period.com.'] namespace = self.parse(short_args) - self.assertEqual(namespace.domains, ['trailing.period.com']) + assert namespace.domains == ['trailing.period.com'] short_args = ['-d', 'example.com,another.net,third.org,example.com'] namespace = self.parse(short_args) - self.assertEqual(namespace.domains, ['example.com', 'another.net', - 'third.org']) + assert namespace.domains == ['example.com', 'another.net', + 'third.org'] long_args = ['--domains', 'example.com'] namespace = self.parse(long_args) - self.assertEqual(namespace.domains, ['example.com']) + assert namespace.domains == ['example.com'] long_args = ['--domains', 'trailing.period.com.'] namespace = self.parse(long_args) - self.assertEqual(namespace.domains, ['trailing.period.com']) + assert namespace.domains == ['trailing.period.com'] long_args = ['--domains', 'example.com,another.net,example.com'] namespace = self.parse(long_args) - self.assertEqual(namespace.domains, ['example.com', 'another.net']) + assert namespace.domains == ['example.com', 'another.net'] def test_preferred_challenges(self): short_args = ['--preferred-challenges', 'http, dns'] namespace = self.parse(short_args) expected = [challenges.HTTP01.typ, challenges.DNS01.typ] - self.assertEqual(namespace.pref_challs, expected) + assert namespace.pref_challs == expected short_args = ['--preferred-challenges', 'jumping-over-the-moon'] # argparse.ArgumentError makes argparse print more information # to stderr and call sys.exit() with mock.patch('sys.stderr'): - self.assertRaises(SystemExit, self.parse, short_args) + with pytest.raises(SystemExit): + self.parse(short_args) def test_server_flag(self): namespace = self.parse('--server example.com'.split()) - self.assertEqual(namespace.server, 'example.com') + assert namespace.server == 'example.com' def test_must_staple_flag(self): short_args = ['--must-staple'] namespace = self.parse(short_args) - self.assertIs(namespace.must_staple, True) - self.assertIs(namespace.staple, True) + assert namespace.must_staple is True + assert namespace.staple is True def _check_server_conflict_message(self, parser_args, conflicting_args): try: @@ -278,36 +280,37 @@ class ParseTest(unittest.TestCase): "The following flags didn't conflict with " '--server: {0}'.format(', '.join(conflicting_args))) except errors.Error as error: - self.assertIn('--server', str(error)) + assert '--server' in str(error) for arg in conflicting_args: - self.assertIn(arg, str(error)) + assert arg in str(error) def test_staging_flag(self): short_args = ['--staging'] namespace = self.parse(short_args) - self.assertIs(namespace.staging, True) - self.assertEqual(namespace.server, constants.STAGING_URI) + assert namespace.staging is True + assert namespace.server == constants.STAGING_URI short_args += '--server example.com'.split() self._check_server_conflict_message(short_args, '--staging') def _assert_dry_run_flag_worked(self, namespace, existing_account): - self.assertIs(namespace.dry_run, True) - self.assertIs(namespace.break_my_certs, True) - self.assertIs(namespace.staging, True) - self.assertEqual(namespace.server, constants.STAGING_URI) + assert namespace.dry_run is True + assert namespace.break_my_certs is True + assert namespace.staging is True + assert namespace.server == constants.STAGING_URI if existing_account: - self.assertIs(namespace.tos, True) - self.assertIs(namespace.register_unsafely_without_email, True) + assert namespace.tos is True + assert namespace.register_unsafely_without_email is True else: - self.assertIs(namespace.tos, False) - self.assertIs(namespace.register_unsafely_without_email, False) + assert namespace.tos is False + assert namespace.register_unsafely_without_email is False def test_dry_run_flag(self): config_dir = tempfile.mkdtemp() short_args = '--dry-run --config-dir {0}'.format(config_dir).split() - self.assertRaises(errors.Error, self.parse, short_args) + with pytest.raises(errors.Error): + self.parse(short_args) self._assert_dry_run_flag_worked( self.parse(short_args + ['auth']), False) @@ -327,16 +330,16 @@ class ParseTest(unittest.TestCase): short_args += ['certonly'] # `--dry-run --server example.com` should emit example.com - self.assertEqual(self.parse(short_args + ['--server', 'example.com']).server, - 'example.com') + assert self.parse(short_args + ['--server', 'example.com']).server == \ + 'example.com' # `--dry-run --server STAGING_URI` should emit STAGING_URI - self.assertEqual(self.parse(short_args + ['--server', constants.STAGING_URI]).server, - constants.STAGING_URI) + assert self.parse(short_args + ['--server', constants.STAGING_URI]).server == \ + constants.STAGING_URI # `--dry-run --server LIVE` should emit STAGING_URI - self.assertEqual(self.parse(short_args + ['--server', cli.flag_default("server")]).server, - constants.STAGING_URI) + assert self.parse(short_args + ['--server', cli.flag_default("server")]).server == \ + constants.STAGING_URI # `--dry-run --server example.com --staging` should emit an error conflicts = ['--staging'] @@ -348,134 +351,134 @@ class ParseTest(unittest.TestCase): key_size_value = cli.flag_default(key_size_option) self.parse('--rsa-key-size {0}'.format(key_size_value).split()) - self.assertIs(cli.option_was_set(key_size_option, key_size_value), True) - self.assertIs(cli.option_was_set('no_verify_ssl', True), True) + assert cli.option_was_set(key_size_option, key_size_value) is True + assert cli.option_was_set('no_verify_ssl', True) is True config_dir_option = 'config_dir' - self.assertFalse(cli.option_was_set( - config_dir_option, cli.flag_default(config_dir_option))) - self.assertFalse(cli.option_was_set( - 'authenticator', cli.flag_default('authenticator'))) + assert not cli.option_was_set( + config_dir_option, cli.flag_default(config_dir_option)) + assert not cli.option_was_set( + 'authenticator', cli.flag_default('authenticator')) def test_ecdsa_key_option(self): elliptic_curve_option = 'elliptic_curve' elliptic_curve_option_value = cli.flag_default(elliptic_curve_option) self.parse('--elliptic-curve {0}'.format(elliptic_curve_option_value).split()) - self.assertIs(cli.option_was_set(elliptic_curve_option, elliptic_curve_option_value), True) + assert cli.option_was_set(elliptic_curve_option, elliptic_curve_option_value) is True def test_invalid_key_type(self): key_type_option = 'key_type' key_type_value = cli.flag_default(key_type_option) self.parse('--key-type {0}'.format(key_type_value).split()) - self.assertIs(cli.option_was_set(key_type_option, key_type_value), True) + assert cli.option_was_set(key_type_option, key_type_value) is True - with self.assertRaises(SystemExit): + with pytest.raises(SystemExit): self.parse("--key-type foo") def test_encode_revocation_reason(self): for reason, code in constants.REVOCATION_REASONS.items(): namespace = self.parse(['--reason', reason]) - self.assertEqual(namespace.reason, code) + assert namespace.reason == code for reason, code in constants.REVOCATION_REASONS.items(): namespace = self.parse(['--reason', reason.upper()]) - self.assertEqual(namespace.reason, code) + assert namespace.reason == code def test_force_interactive(self): - self.assertRaises( - errors.Error, self.parse, "renew --force-interactive".split()) - self.assertRaises( - errors.Error, self.parse, "-n --force-interactive".split()) + with pytest.raises(errors.Error): + self.parse("renew --force-interactive".split()) + with pytest.raises(errors.Error): + self.parse("-n --force-interactive".split()) def test_deploy_hook_conflict(self): with mock.patch("certbot._internal.cli.sys.stderr"): - self.assertRaises(SystemExit, self.parse, - "--renew-hook foo --deploy-hook bar".split()) + with pytest.raises(SystemExit): + self.parse("--renew-hook foo --deploy-hook bar".split()) def test_deploy_hook_matches_renew_hook(self): value = "foo" namespace = self.parse(["--renew-hook", value, "--deploy-hook", value, "--disable-hook-validation"]) - self.assertEqual(namespace.deploy_hook, value) - self.assertEqual(namespace.renew_hook, value) + assert namespace.deploy_hook == value + assert namespace.renew_hook == value def test_deploy_hook_sets_renew_hook(self): value = "foo" namespace = self.parse( ["--deploy-hook", value, "--disable-hook-validation"]) - self.assertEqual(namespace.deploy_hook, value) - self.assertEqual(namespace.renew_hook, value) + assert namespace.deploy_hook == value + assert namespace.renew_hook == value def test_renew_hook_conflict(self): with mock.patch("certbot._internal.cli.sys.stderr"): - self.assertRaises(SystemExit, self.parse, - "--deploy-hook foo --renew-hook bar".split()) + with pytest.raises(SystemExit): + self.parse("--deploy-hook foo --renew-hook bar".split()) def test_renew_hook_matches_deploy_hook(self): value = "foo" namespace = self.parse(["--deploy-hook", value, "--renew-hook", value, "--disable-hook-validation"]) - self.assertEqual(namespace.deploy_hook, value) - self.assertEqual(namespace.renew_hook, value) + assert namespace.deploy_hook == value + assert namespace.renew_hook == value def test_renew_hook_does_not_set_renew_hook(self): value = "foo" namespace = self.parse( ["--renew-hook", value, "--disable-hook-validation"]) - self.assertIsNone(namespace.deploy_hook) - self.assertEqual(namespace.renew_hook, value) + assert namespace.deploy_hook is None + assert namespace.renew_hook == value def test_max_log_backups_error(self): with mock.patch('certbot._internal.cli.sys.stderr'): - self.assertRaises( - SystemExit, self.parse, "--max-log-backups foo".split()) - self.assertRaises( - SystemExit, self.parse, "--max-log-backups -42".split()) + with pytest.raises(SystemExit): + self.parse("--max-log-backups foo".split()) + with pytest.raises(SystemExit): + self.parse("--max-log-backups -42".split()) def test_max_log_backups_success(self): value = "42" namespace = self.parse(["--max-log-backups", value]) - self.assertEqual(namespace.max_log_backups, int(value)) + assert namespace.max_log_backups == int(value) def test_unchanging_defaults(self): namespace = self.parse([]) - self.assertEqual(namespace.domains, []) - self.assertEqual(namespace.pref_challs, []) + assert namespace.domains == [] + assert namespace.pref_challs == [] namespace.pref_challs = [challenges.HTTP01.typ] namespace.domains = ['example.com'] namespace = self.parse([]) - self.assertEqual(namespace.domains, []) - self.assertEqual(namespace.pref_challs, []) + assert namespace.domains == [] + assert namespace.pref_challs == [] def test_no_directory_hooks_set(self): - self.assertFalse(self.parse(["--no-directory-hooks"]).directory_hooks) + assert not self.parse(["--no-directory-hooks"]).directory_hooks def test_no_directory_hooks_unset(self): - self.assertIs(self.parse([]).directory_hooks, True) + assert self.parse([]).directory_hooks is True def test_delete_after_revoke(self): namespace = self.parse(["--delete-after-revoke"]) - self.assertIs(namespace.delete_after_revoke, True) + assert namespace.delete_after_revoke is True def test_delete_after_revoke_default(self): namespace = self.parse([]) - self.assertIsNone(namespace.delete_after_revoke) + assert namespace.delete_after_revoke is None def test_no_delete_after_revoke(self): namespace = self.parse(["--no-delete-after-revoke"]) - self.assertIs(namespace.delete_after_revoke, False) + assert namespace.delete_after_revoke is False def test_allow_subset_with_wildcard(self): - self.assertRaises(errors.Error, self.parse, - "--allow-subset-of-names -d *.example.org".split()) + with pytest.raises(errors.Error): + self.parse("--allow-subset-of-names -d *.example.org".split()) def test_route53_no_revert(self): for help_flag in ['-h', '--help']: for topic in ['all', 'plugins', 'dns-route53']: - self.assertNotIn('certbot-route53:auth', self._help_output([help_flag, topic])) + assert 'certbot-route53:auth' not in self._help_output([help_flag, topic]) class DefaultTest(unittest.TestCase): @@ -488,14 +491,14 @@ class DefaultTest(unittest.TestCase): self.default2 = cli._Default() def test_boolean(self): - self.assertIs(bool(self.default1), False) - self.assertIs(bool(self.default2), False) + assert bool(self.default1) is False + assert bool(self.default2) is False def test_equality(self): - self.assertEqual(self.default1, self.default2) + assert self.default1 == self.default2 def test_hash(self): - self.assertEqual(hash(self.default1), hash(self.default2)) + assert hash(self.default1) == hash(self.default2) class SetByCliTest(unittest.TestCase): @@ -506,13 +509,13 @@ class SetByCliTest(unittest.TestCase): reload_module(cli) def test_deploy_hook(self): - self.assertTrue(_call_set_by_cli( - 'renew_hook', '--deploy-hook foo'.split(), 'renew')) + assert _call_set_by_cli( + 'renew_hook', '--deploy-hook foo'.split(), 'renew') def test_webroot_map(self): args = '-w /var/www/html -d example.com'.split() verb = 'renew' - self.assertIs(_call_set_by_cli('webroot_map', args, verb), True) + assert _call_set_by_cli('webroot_map', args, verb) is True def _call_set_by_cli(var, args, verb): diff --git a/certbot/tests/client_test.py b/certbot/tests/client_test.py index 405858e97..1e1b0219c 100644 --- a/certbot/tests/client_test.py +++ b/certbot/tests/client_test.py @@ -103,12 +103,13 @@ class RegisterTest(test_util.ConfigTestCase): mock_client().external_account_required.side_effect = self._false_mock with mock.patch("certbot._internal.eff.prepare_subscription") as mock_prepare: mock_client().new_account.side_effect = errors.Error - self.assertRaises(errors.Error, self._call) - self.assertIs(mock_prepare.called, False) + with pytest.raises(errors.Error): + self._call() + assert mock_prepare.called is False mock_client().new_account.side_effect = None self._call() - self.assertIs(mock_prepare.called, True) + assert mock_prepare.called is True @mock.patch('certbot._internal.eff.prepare_subscription') def test_empty_meta(self, unused_mock_prepare): @@ -121,7 +122,7 @@ class RegisterTest(test_util.ConfigTestCase): mock_client().external_account_required.side_effect = self._false_mock self._call() - self.assertIs(self.tos_cb.called, False) + assert self.tos_cb.called is False @test_util.patch_display_util() def test_it(self, unused_mock_get_utility): @@ -129,7 +130,7 @@ class RegisterTest(test_util.ConfigTestCase): mock_client().external_account_required.side_effect = self._false_mock with mock.patch("certbot._internal.eff.handle_subscription"): self._call() - self.assertIs(self.tos_cb.called, True) + assert self.tos_cb.called is True @mock.patch("certbot._internal.client.display_ops.get_email") def test_email_retry(self, mock_get_email): @@ -142,8 +143,8 @@ class RegisterTest(test_util.ConfigTestCase): with mock.patch("certbot._internal.eff.prepare_subscription") as mock_prepare: mock_client().new_account.side_effect = [mx_err, mock.MagicMock()] self._call() - self.assertEqual(mock_get_email.call_count, 1) - self.assertIs(mock_prepare.called, True) + assert mock_get_email.call_count == 1 + assert mock_prepare.called is True def test_email_invalid_noninteractive(self): from acme import messages @@ -154,11 +155,13 @@ class RegisterTest(test_util.ConfigTestCase): mock_client().external_account_required.side_effect = self._false_mock with mock.patch("certbot._internal.eff.handle_subscription"): mock_client().new_account.side_effect = [mx_err, mock.MagicMock()] - self.assertRaises(errors.Error, self._call) + with pytest.raises(errors.Error): + self._call() def test_needs_email(self): self.config.email = None - self.assertRaises(errors.Error, self._call) + with pytest.raises(errors.Error): + self._call() @mock.patch("certbot._internal.client.logger") def test_without_email(self, mock_logger): @@ -170,7 +173,7 @@ class RegisterTest(test_util.ConfigTestCase): self.config.dry_run = False self._call() mock_logger.debug.assert_called_once_with(mock.ANY) - self.assertIs(mock_prepare.called, True) + assert mock_prepare.called is True @mock.patch("certbot._internal.client.display_ops.get_email") def test_dry_run_no_staging_account(self, mock_get_email): @@ -181,9 +184,9 @@ class RegisterTest(test_util.ConfigTestCase): self.config.dry_run = True self._call() # check Certbot did not ask the user to provide an email - self.assertIs(mock_get_email.called, False) + assert mock_get_email.called is False # check Certbot created an account with no email. Contact should return empty - self.assertFalse(mock_client().new_account.call_args[0][0].contact) + assert not mock_client().new_account.call_args[0][0].contact @test_util.patch_display_util() def test_with_eab_arguments(self, unused_mock_get_utility): @@ -199,7 +202,7 @@ class RegisterTest(test_util.ConfigTestCase): self.config.eab_hmac_key = "J2OAqW4MHXsrHVa_PVg0Y-L_R4SYw0_aL1le6mfblbE" self._call() - self.assertIs(mock_eab_from_data.called, True) + assert mock_eab_from_data.called is True @test_util.patch_display_util() def test_without_eab_arguments(self, unused_mock_get_utility): @@ -212,7 +215,7 @@ class RegisterTest(test_util.ConfigTestCase): self.config.eab_hmac_key = None self._call() - self.assertIs(mock_eab_from_data.called, False) + assert mock_eab_from_data.called is False def test_external_account_required_without_eab_arguments(self): with self._patched_acme_client() as mock_client: @@ -223,7 +226,8 @@ class RegisterTest(test_util.ConfigTestCase): self.config.eab_kid = None self.config.eab_hmac_key = None - self.assertRaises(errors.Error, self._call) + with pytest.raises(errors.Error): + self._call() def test_unsupported_error(self): from acme import messages @@ -236,8 +240,9 @@ class RegisterTest(test_util.ConfigTestCase): mock_client().external_account_required.side_effect = self._false_mock with mock.patch("certbot._internal.eff.handle_subscription") as mock_handle: mock_client().new_account.side_effect = [mx_err, mock.MagicMock()] - self.assertRaises(messages.Error, self._call) - self.assertIs(mock_handle.called, False) + with pytest.raises(messages.Error): + self._call() + assert mock_handle.called is False class ClientTestCommon(test_util.ConfigTestCase): @@ -275,7 +280,7 @@ class ClientTest(ClientTestCommon): csr_pem=mock.sentinel.csr_pem) def test_init_acme_verify_ssl(self): - self.assertIs(self.client_network.call_args[1]['verify_ssl'], True) + assert self.client_network.call_args[1]['verify_ssl'] is True def _mock_obtain_certificate(self): self.client.auth_handler = mock.MagicMock() @@ -292,7 +297,7 @@ class ClientTest(ClientTestCommon): self.config, self.config.allow_subset_of_names) else: - self.assertEqual(self.client.auth_handler.handle_authorizations.call_count, auth_count) + assert self.client.auth_handler.handle_authorizations.call_count == auth_count self.acme.finalize_order.assert_called_once_with( self.eg_order, mock.ANY, @@ -308,22 +313,20 @@ class ClientTest(ClientTestCommon): orderr = self.acme.new_order(test_csr.data) auth_handler.handle_authorizations(orderr, self.config, False) - self.assertEqual( - (mock.sentinel.cert, mock.sentinel.chain), + assert (mock.sentinel.cert, mock.sentinel.chain) == \ self.client.obtain_certificate_from_csr( test_csr, - orderr=orderr)) + orderr=orderr) mock_crypto_util.find_chain_with_issuer.assert_not_called() # and that the cert was obtained correctly self._check_obtain_certificate() # Test that --preferred-chain results in chain selection self.config.preferred_chain = "some issuer" - self.assertEqual( - (mock.sentinel.cert, mock.sentinel.chain), + assert (mock.sentinel.cert, mock.sentinel.chain) == \ self.client.obtain_certificate_from_csr( test_csr, - orderr=orderr)) + orderr=orderr) mock_crypto_util.find_chain_with_issuer.assert_called_once_with( [orderr.fullchain_pem] + orderr.alternative_fullchains_pem, "some issuer", True) @@ -335,8 +338,7 @@ class ClientTest(ClientTestCommon): seconds=constants.CLI_DEFAULTS["issuance_timeout"]) self.client.obtain_certificate_from_csr(test_csr, orderr=orderr) ((_, deadline), _) = self.client.acme.finalize_order.call_args - self.assertTrue( - abs(expected_deadline - deadline) <= datetime.timedelta(seconds=1)) + assert abs(expected_deadline - deadline) <= datetime.timedelta(seconds=1) # Test for specific issuance_timeout (300 seconds) expected_deadline = \ @@ -344,23 +346,19 @@ class ClientTest(ClientTestCommon): self.config.issuance_timeout = 300 self.client.obtain_certificate_from_csr(test_csr, orderr=orderr) ((_, deadline), _) = self.client.acme.finalize_order.call_args - self.assertTrue( - abs(expected_deadline - deadline) <= datetime.timedelta(seconds=1)) + assert abs(expected_deadline - deadline) <= datetime.timedelta(seconds=1) # Test for orderr=None - self.assertEqual( - (mock.sentinel.cert, mock.sentinel.chain), + assert (mock.sentinel.cert, mock.sentinel.chain) == \ self.client.obtain_certificate_from_csr( test_csr, - orderr=None)) + orderr=None) auth_handler.handle_authorizations.assert_called_with(self.eg_order, self.config, False) # Test for no auth_handler self.client.auth_handler = None - self.assertRaises( - errors.Error, - self.client.obtain_certificate_from_csr, - test_csr) + with pytest.raises(errors.Error): + self.client.obtain_certificate_from_csr(test_csr) mock_logger.error.assert_called_once_with(mock.ANY) @mock.patch("certbot._internal.client.crypto_util") @@ -396,9 +394,9 @@ class ClientTest(ClientTestCommon): self.config.allow_subset_of_names = True self._test_obtain_certificate_common(key, csr, authzr_ret=authzr, auth_count=2) - self.assertEqual(mock_crypto_util.generate_key.call_count, 2) - self.assertEqual(mock_crypto_util.generate_csr.call_count, 2) - self.assertEqual(mock_crypto_util.cert_and_chain_from_fullchain.call_count, 1) + assert mock_crypto_util.generate_key.call_count == 2 + assert mock_crypto_util.generate_csr.call_count == 2 + assert mock_crypto_util.cert_and_chain_from_fullchain.call_count == 1 @mock.patch("certbot._internal.client.crypto_util") def test_obtain_certificate_finalize_order_partial_success(self, mock_crypto_util): @@ -424,18 +422,17 @@ class ClientTest(ClientTestCommon): with test_util.patch_display_util(): result = self.client.obtain_certificate(self.eg_domains) - self.assertEqual( - result, - (mock.sentinel.cert, mock.sentinel.chain, key, csr)) - self.assertEqual(self.client.auth_handler.handle_authorizations.call_count, 2) - self.assertEqual(self.acme.finalize_order.call_count, 2) + assert result == \ + (mock.sentinel.cert, mock.sentinel.chain, key, csr) + assert self.client.auth_handler.handle_authorizations.call_count == 2 + assert self.acme.finalize_order.call_count == 2 successful_domains = [d for d in self.eg_domains if d != 'example.com'] - self.assertEqual(mock_crypto_util.generate_key.call_count, 2) + assert mock_crypto_util.generate_key.call_count == 2 mock_crypto_util.generate_csr.assert_has_calls([ mock.call(key, self.eg_domains, None, self.config.must_staple, self.config.strict_permissions), mock.call(key, successful_domains, None, self.config.must_staple, self.config.strict_permissions)]) - self.assertEqual(mock_crypto_util.cert_and_chain_from_fullchain.call_count, 1) + assert mock_crypto_util.cert_and_chain_from_fullchain.call_count == 1 @mock.patch("certbot._internal.client.crypto_util") def test_obtain_certificate_finalize_order_no_retryable_domains(self, mock_crypto_util): @@ -460,11 +457,12 @@ class ClientTest(ClientTestCommon): self.config.allow_subset_of_names = True - self.assertRaises(messages.Error, self.client.obtain_certificate, self.eg_domains) - self.assertEqual(self.client.auth_handler.handle_authorizations.call_count, 1) - self.assertEqual(self.acme.finalize_order.call_count, 1) - self.assertEqual(mock_crypto_util.generate_key.call_count, 1) - self.assertEqual(mock_crypto_util.cert_and_chain_from_fullchain.call_count, 0) + with pytest.raises(messages.Error): + self.client.obtain_certificate(self.eg_domains) + assert self.client.auth_handler.handle_authorizations.call_count == 1 + assert self.acme.finalize_order.call_count == 1 + assert mock_crypto_util.generate_key.call_count == 1 + assert mock_crypto_util.cert_and_chain_from_fullchain.call_count == 0 @mock.patch("certbot._internal.client.crypto_util") def test_obtain_certificate_finalize_order_rejected_identifier_no_subproblems(self, mock_crypto_util): @@ -485,12 +483,12 @@ class ClientTest(ClientTestCommon): self.config.allow_subset_of_names = True - self.assertRaises(messages.Error, self.client.obtain_certificate, - self.eg_domains) - self.assertEqual(self.client.auth_handler.handle_authorizations.call_count, 1) - self.assertEqual(self.acme.finalize_order.call_count, 1) - self.assertEqual(mock_crypto_util.generate_key.call_count, 1) - self.assertEqual(mock_crypto_util.cert_and_chain_from_fullchain.call_count, 0) + with pytest.raises(messages.Error): + self.client.obtain_certificate(self.eg_domains) + assert self.client.auth_handler.handle_authorizations.call_count == 1 + assert self.acme.finalize_order.call_count == 1 + assert mock_crypto_util.generate_key.call_count == 1 + assert mock_crypto_util.cert_and_chain_from_fullchain.call_count == 0 @mock.patch("certbot._internal.client.crypto_util") def test_obtain_certificate_get_order_partial_success(self, mock_crypto_util): @@ -516,18 +514,17 @@ class ClientTest(ClientTestCommon): with test_util.patch_display_util(): result = self.client.obtain_certificate(self.eg_domains) - self.assertEqual( - result, - (mock.sentinel.cert, mock.sentinel.chain, key, csr)) - self.assertEqual(self.client.auth_handler.handle_authorizations.call_count, 1) - self.assertEqual(self.acme.new_order.call_count, 2) + assert result == \ + (mock.sentinel.cert, mock.sentinel.chain, key, csr) + assert self.client.auth_handler.handle_authorizations.call_count == 1 + assert self.acme.new_order.call_count == 2 successful_domains = [d for d in self.eg_domains if d != 'example.com'] - self.assertEqual(mock_crypto_util.generate_key.call_count, 2) + assert mock_crypto_util.generate_key.call_count == 2 mock_crypto_util.generate_csr.assert_has_calls([ mock.call(key, self.eg_domains, None, self.config.must_staple, self.config.strict_permissions), mock.call(key, successful_domains, None, self.config.must_staple, self.config.strict_permissions)]) - self.assertEqual(mock_crypto_util.cert_and_chain_from_fullchain.call_count, 1) + assert mock_crypto_util.cert_and_chain_from_fullchain.call_count == 1 @mock.patch("certbot._internal.client.crypto_util") def test_obtain_certificate_get_order_no_retryable_domains(self, mock_crypto_util): @@ -552,11 +549,12 @@ class ClientTest(ClientTestCommon): self.config.allow_subset_of_names = True - self.assertRaises(messages.Error, self.client.obtain_certificate, self.eg_domains) - self.assertEqual(self.client.auth_handler.handle_authorizations.call_count, 0) - self.assertEqual(self.acme.new_order.call_count, 1) - self.assertEqual(mock_crypto_util.generate_key.call_count, 1) - self.assertEqual(mock_crypto_util.cert_and_chain_from_fullchain.call_count, 0) + with pytest.raises(messages.Error): + self.client.obtain_certificate(self.eg_domains) + assert self.client.auth_handler.handle_authorizations.call_count == 0 + assert self.acme.new_order.call_count == 1 + assert mock_crypto_util.generate_key.call_count == 1 + assert mock_crypto_util.cert_and_chain_from_fullchain.call_count == 0 @mock.patch("certbot._internal.client.crypto_util") def test_obtain_certificate_get_order_rejected_identifier_no_subproblems(self, mock_crypto_util): @@ -577,11 +575,12 @@ class ClientTest(ClientTestCommon): self.config.allow_subset_of_names = True - self.assertRaises(messages.Error, self.client.obtain_certificate, self.eg_domains) - self.assertEqual(self.client.auth_handler.handle_authorizations.call_count, 0) - self.assertEqual(self.acme.new_order.call_count, 1) - self.assertEqual(mock_crypto_util.generate_key.call_count, 1) - self.assertEqual(mock_crypto_util.cert_and_chain_from_fullchain.call_count, 0) + with pytest.raises(messages.Error): + self.client.obtain_certificate(self.eg_domains) + assert self.client.auth_handler.handle_authorizations.call_count == 0 + assert self.acme.new_order.call_count == 1 + assert mock_crypto_util.generate_key.call_count == 1 + assert mock_crypto_util.cert_and_chain_from_fullchain.call_count == 0 @mock.patch("certbot._internal.client.crypto_util") @mock.patch("certbot._internal.client.acme_crypto_util") @@ -604,7 +603,7 @@ class ClientTest(ClientTestCommon): mock.sentinel.key_pem, self.eg_domains, self.config.must_staple) mock_crypto.generate_key.assert_not_called() mock_crypto.generate_csr.assert_not_called() - self.assertEqual(mock_crypto.cert_and_chain_from_fullchain.call_count, 1) + assert mock_crypto.cert_and_chain_from_fullchain.call_count == 1 @mock.patch("certbot._internal.client.logger") @mock.patch("certbot._internal.client.crypto_util") @@ -635,14 +634,14 @@ class ClientTest(ClientTestCommon): self.client.auth_handler.handle_authorizations.return_value = authzrs with test_util.patch_display_util(): result = self.client.obtain_certificate(self.eg_domains) - self.assertEqual(result, (mock.sentinel.cert, mock.sentinel.chain, key, csr)) + assert result == (mock.sentinel.cert, mock.sentinel.chain, key, csr) self._check_obtain_certificate(1) # Deactivation success/failure should have been handled properly - self.assertEqual(auth_handler.deactivate_valid_authorizations.call_count, 1, - "Deactivate authorizations should be called") - self.assertEqual(self.acme.new_order.call_count, 2, - "Order should be recreated due to successfully deactivated authorizations") + assert auth_handler.deactivate_valid_authorizations.call_count == 1, \ + "Deactivate authorizations should be called" + assert self.acme.new_order.call_count == 2, \ + "Order should be recreated due to successfully deactivated authorizations" mock_log.warning.assert_called_with("Certbot was unable to obtain fresh authorizations for" " every domain. The dry run will continue, but results" " may not be accurate.") @@ -680,9 +679,8 @@ class ClientTest(ClientTestCommon): with test_util.patch_display_util(): result = self.client.obtain_certificate(self.eg_domains) - self.assertEqual( - result, - (mock.sentinel.cert, mock.sentinel.chain, key, csr)) + assert result == \ + (mock.sentinel.cert, mock.sentinel.chain, key, csr) self._check_obtain_certificate(auth_count) @mock.patch('certbot._internal.client.Client.obtain_certificate') @@ -694,17 +692,17 @@ class ClientTest(ClientTestCommon): mock.MagicMock(), mock.MagicMock(), None) self.client.config.dry_run = False - self.assertTrue(self.client.obtain_and_enroll_certificate(domains, "example_cert")) + assert self.client.obtain_and_enroll_certificate(domains, "example_cert") - self.assertTrue(self.client.obtain_and_enroll_certificate(domains, None)) - self.assertTrue(self.client.obtain_and_enroll_certificate(domains[1:], None)) + assert self.client.obtain_and_enroll_certificate(domains, None) + assert self.client.obtain_and_enroll_certificate(domains[1:], None) self.client.config.dry_run = True - self.assertFalse(self.client.obtain_and_enroll_certificate(domains, None)) + assert not self.client.obtain_and_enroll_certificate(domains, None) names = [call[0][0] for call in mock_storage.call_args_list] - self.assertEqual(names, ["example_cert", "example.com", "example.com"]) + assert names == ["example_cert", "example.com", "example.com"] @mock.patch("certbot._internal.cli.helpful_parser") def test_save_certificate(self, mock_parser): @@ -725,28 +723,28 @@ class ClientTest(ClientTestCommon): cert_pem, chain_pem, candidate_cert_path, candidate_chain_path, candidate_fullchain_path) - self.assertEqual(os.path.dirname(cert_path), - os.path.dirname(candidate_cert_path)) - self.assertEqual(os.path.dirname(chain_path), - os.path.dirname(candidate_chain_path)) - self.assertEqual(os.path.dirname(fullchain_path), - os.path.dirname(candidate_fullchain_path)) + assert os.path.dirname(cert_path) == \ + os.path.dirname(candidate_cert_path) + assert os.path.dirname(chain_path) == \ + os.path.dirname(candidate_chain_path) + assert os.path.dirname(fullchain_path) == \ + os.path.dirname(candidate_fullchain_path) with open(cert_path, "rb") as cert_file: cert_contents = cert_file.read() - self.assertEqual(cert_contents, test_util.load_vector(certs[0])) + assert cert_contents == test_util.load_vector(certs[0]) with open(chain_path, "rb") as chain_file: chain_contents = chain_file.read() - self.assertEqual(chain_contents, test_util.load_vector(certs[0]) + - test_util.load_vector(certs[1])) + assert chain_contents == test_util.load_vector(certs[0]) + \ + test_util.load_vector(certs[1]) shutil.rmtree(tmp_path) @test_util.patch_display_util() def test_deploy_certificate_success(self, mock_util): - self.assertRaises(errors.Error, self.client.deploy_certificate, - ["foo.bar"], "key", "cert", "chain", "fullchain") + with pytest.raises(errors.Error): + self.client.deploy_certificate(["foo.bar"], "key", "cert", "chain", "fullchain") installer = mock.MagicMock() self.client.installer = installer @@ -758,7 +756,7 @@ class ClientTest(ClientTestCommon): domain='foo.bar', fullchain_path='fullchain', key_path=os.path.abspath("key")) - self.assertEqual(installer.save.call_count, 2) + assert installer.save.call_count == 2 installer.restart.assert_called_once_with() @mock.patch('certbot._internal.client.display_util.notify') @@ -769,8 +767,8 @@ class ClientTest(ClientTestCommon): self.config.installer = "foobar" installer.deploy_cert.side_effect = errors.PluginError - self.assertRaises(errors.PluginError, self.client.deploy_certificate, - ["foo.bar"], "key", "cert", "chain", "fullchain") + with pytest.raises(errors.PluginError): + self.client.deploy_certificate(["foo.bar"], "key", "cert", "chain", "fullchain") installer.recovery_routine.assert_called_once_with() mock_notify.assert_any_call('Deploying certificate') @@ -782,8 +780,8 @@ class ClientTest(ClientTestCommon): self.client.installer = installer installer.save.side_effect = errors.PluginError - self.assertRaises(errors.PluginError, self.client.deploy_certificate, - ["foo.bar"], "key", "cert", "chain", "fullchain") + with pytest.raises(errors.PluginError): + self.client.deploy_certificate(["foo.bar"], "key", "cert", "chain", "fullchain") installer.recovery_routine.assert_called_once_with() @mock.patch('certbot._internal.client.display_util.notify') @@ -793,13 +791,13 @@ class ClientTest(ClientTestCommon): installer.restart.side_effect = [errors.PluginError, None] self.client.installer = installer - self.assertRaises(errors.PluginError, self.client.deploy_certificate, - ["foo.bar"], "key", "cert", "chain", "fullchain") + with pytest.raises(errors.PluginError): + self.client.deploy_certificate(["foo.bar"], "key", "cert", "chain", "fullchain") mock_notify.assert_called_with( 'We were unable to install your certificate, however, we successfully restored ' 'your server to its prior configuration.') installer.rollback_checkpoints.assert_called_once_with() - self.assertEqual(installer.restart.call_count, 2) + assert installer.restart.call_count == 2 @mock.patch('certbot._internal.client.logger') @test_util.patch_display_util() @@ -809,14 +807,13 @@ class ClientTest(ClientTestCommon): installer.rollback_checkpoints.side_effect = errors.ReverterError self.client.installer = installer - self.assertRaises(errors.PluginError, self.client.deploy_certificate, - ["foo.bar"], "key", "cert", "chain", "fullchain") - self.assertEqual(mock_logger.error.call_count, 1) - self.assertIn( - 'An error occurred and we failed to restore your config', - mock_logger.error.call_args[0][0]) + with pytest.raises(errors.PluginError): + self.client.deploy_certificate(["foo.bar"], "key", "cert", "chain", "fullchain") + assert mock_logger.error.call_count == 1 + assert 'An error occurred and we failed to restore your config' in \ + mock_logger.error.call_args[0][0] installer.rollback_checkpoints.assert_called_once_with() - self.assertEqual(installer.restart.call_count, 1) + assert installer.restart.call_count == 1 class EnhanceConfigTest(ClientTestCommon): @@ -832,8 +829,8 @@ class EnhanceConfigTest(ClientTestCommon): self.domain = "example.org" def test_no_installer(self): - self.assertRaises( - errors.Error, self.client.enhance_config, [self.domain], None) + with pytest.raises(errors.Error): + self.client.enhance_config([self.domain], None) def test_unsupported(self): self.client.installer = mock.MagicMock() @@ -843,36 +840,36 @@ class EnhanceConfigTest(ClientTestCommon): self.config.hsts = True with mock.patch("certbot._internal.client.logger") as mock_logger: self.client.enhance_config([self.domain], None) - self.assertEqual(mock_logger.error.call_count, 1) + assert mock_logger.error.call_count == 1 self.client.installer.enhance.assert_not_called() @mock.patch("certbot._internal.client.logger") def test_already_exists_header(self, mock_log): self.config.hsts = True self._test_with_already_existing() - self.assertIs(mock_log.info.called, True) - self.assertEqual(mock_log.info.call_args[0][1], - 'Strict-Transport-Security') + assert mock_log.info.called is True + assert mock_log.info.call_args[0][1] == \ + 'Strict-Transport-Security' @mock.patch("certbot._internal.client.logger") def test_already_exists_redirect(self, mock_log): self.config.redirect = True self._test_with_already_existing() - self.assertIs(mock_log.info.called, True) - self.assertEqual(mock_log.info.call_args[0][1], - 'redirect') + assert mock_log.info.called is True + assert mock_log.info.call_args[0][1] == \ + 'redirect' @mock.patch("certbot._internal.client.logger") def test_config_set_no_warning_redirect(self, mock_log): self.config.redirect = False self._test_with_already_existing() - self.assertIs(mock_log.warning.called, False) + assert mock_log.warning.called is False @mock.patch("certbot._internal.client.logger") def test_no_warn_redirect(self, mock_log): self.config.redirect = None self._test_with_all_supported() - self.assertIs(mock_log.warning.called, False) + assert mock_log.warning.called is False def test_no_ask_hsts(self): self.config.hsts = True @@ -925,18 +922,18 @@ class EnhanceConfigTest(ClientTestCommon): def _test_error_with_rollback(self): self._test_error() - self.assertIs(self.client.installer.restart.called, True) + assert self.client.installer.restart.called is True def _test_error(self, enhance_error=False, restart_error=False): self.config.redirect = True with mock.patch('certbot._internal.client.logger') as mock_logger, \ test_util.patch_display_util() as mock_gu: - self.assertRaises( - errors.PluginError, self._test_with_all_supported) + with pytest.raises(errors.PluginError): + self._test_with_all_supported() if enhance_error: - self.assertEqual(mock_logger.error.call_count, 1) - self.assertEqual('Unable to set the %s enhancement for %s.', mock_logger.error.call_args_list[0][0][0]) + assert mock_logger.error.call_count == 1 + assert 'Unable to set the %s enhancement for %s.' == mock_logger.error.call_args_list[0][0][0] if restart_error: mock_logger.critical.assert_called_with( 'Rolling back to previous server configuration...') @@ -947,8 +944,8 @@ class EnhanceConfigTest(ClientTestCommon): self.client.installer.supported_enhancements.return_value = [ "ensure-http-header", "redirect", "staple-ocsp"] self.client.enhance_config([self.domain], None) - self.assertEqual(self.client.installer.save.call_count, 1) - self.assertEqual(self.client.installer.restart.call_count, 1) + assert self.client.installer.save.call_count == 1 + assert self.client.installer.restart.call_count == 1 def _test_with_already_existing(self): self.client.installer = mock.MagicMock() @@ -973,8 +970,8 @@ class RollbackTest(unittest.TestCase): def test_no_problems(self): self._call(1, self.m_install) - self.assertEqual(self.m_install().rollback_checkpoints.call_count, 1) - self.assertEqual(self.m_install().restart.call_count, 1) + assert self.m_install().rollback_checkpoints.call_count == 1 + assert self.m_install().restart.call_count == 1 def test_no_installer(self): self._call(1, None) # Just make sure no exceptions are raised diff --git a/certbot/tests/compat/filesystem_test.py b/certbot/tests/compat/filesystem_test.py index a634e34ad..303fbe92b 100644 --- a/certbot/tests/compat/filesystem_test.py +++ b/certbot/tests/compat/filesystem_test.py @@ -48,8 +48,8 @@ class WindowsChmodTests(TempDirTestCase): # Assert the real file is impacted, not the link. cur_dacl_probe = _get_security_dacl(self.probe_path).GetSecurityDescriptorDacl() cur_dacl_link = _get_security_dacl(link_path).GetSecurityDescriptorDacl() - self.assertFalse(filesystem._compare_dacls(ref_dacl_probe, cur_dacl_probe)) # pylint: disable=protected-access - self.assertTrue(filesystem._compare_dacls(ref_dacl_link, cur_dacl_link)) # pylint: disable=protected-access + assert not filesystem._compare_dacls(ref_dacl_probe, cur_dacl_probe) # pylint: disable=protected-access + assert filesystem._compare_dacls(ref_dacl_link, cur_dacl_link) # pylint: disable=protected-access def test_world_permission(self): everybody = win32security.ConvertStringSidToSid(EVERYBODY_SID) @@ -57,14 +57,14 @@ class WindowsChmodTests(TempDirTestCase): filesystem.chmod(self.probe_path, 0o700) dacl = _get_security_dacl(self.probe_path).GetSecurityDescriptorDacl() - self.assertFalse([dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) - if dacl.GetAce(index)[2] == everybody]) + assert not [dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) + if dacl.GetAce(index)[2] == everybody] filesystem.chmod(self.probe_path, 0o704) dacl = _get_security_dacl(self.probe_path).GetSecurityDescriptorDacl() - self.assertTrue([dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) - if dacl.GetAce(index)[2] == everybody]) + assert [dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) + if dacl.GetAce(index)[2] == everybody] def test_group_permissions_noop(self): filesystem.chmod(self.probe_path, 0o700) @@ -73,7 +73,7 @@ class WindowsChmodTests(TempDirTestCase): filesystem.chmod(self.probe_path, 0o740) cur_dacl_probe = _get_security_dacl(self.probe_path).GetSecurityDescriptorDacl() - self.assertTrue(filesystem._compare_dacls(ref_dacl_probe, cur_dacl_probe)) # pylint: disable=protected-access + assert filesystem._compare_dacls(ref_dacl_probe, cur_dacl_probe) # pylint: disable=protected-access def test_admin_permissions(self): system = win32security.ConvertStringSidToSid(SYSTEM_SID) @@ -87,11 +87,11 @@ class WindowsChmodTests(TempDirTestCase): admin_aces = [dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) if dacl.GetAce(index)[2] == admins] - self.assertEqual(len(system_aces), 1) - self.assertEqual(len(admin_aces), 1) + assert len(system_aces) == 1 + assert len(admin_aces) == 1 - self.assertEqual(system_aces[0][1], ntsecuritycon.FILE_ALL_ACCESS) - self.assertEqual(admin_aces[0][1], ntsecuritycon.FILE_ALL_ACCESS) + assert system_aces[0][1] == ntsecuritycon.FILE_ALL_ACCESS + assert admin_aces[0][1] == ntsecuritycon.FILE_ALL_ACCESS def test_read_flag(self): self._test_flag(4, ntsecuritycon.FILE_GENERIC_READ) @@ -118,11 +118,11 @@ class WindowsChmodTests(TempDirTestCase): acls_everybody = [dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) if dacl.GetAce(index)[2] == everybody] - self.assertEqual(len(acls_everybody), 1) + assert len(acls_everybody) == 1 acls_everybody = acls_everybody[0] - self.assertEqual(acls_everybody[1], windows_flag) + assert acls_everybody[1] == windows_flag def test_user_admin_dacl_consistency(self): # Set ownership of target to authenticated user @@ -134,7 +134,7 @@ class WindowsChmodTests(TempDirTestCase): security_dacl = _get_security_dacl(self.probe_path) # We expect three ACE: one for admins, one for system, and one for the user - self.assertEqual(security_dacl.GetSecurityDescriptorDacl().GetAceCount(), 3) + assert security_dacl.GetSecurityDescriptorDacl().GetAceCount() == 3 # Set ownership of target to Administrators user group admin_user = win32security.ConvertStringSidToSid(ADMINS_SID) @@ -146,7 +146,7 @@ class WindowsChmodTests(TempDirTestCase): security_dacl = _get_security_dacl(self.probe_path) # We expect only two ACE: one for admins, one for system, # since the user is also the admins group - self.assertEqual(security_dacl.GetSecurityDescriptorDacl().GetAceCount(), 2) + assert security_dacl.GetSecurityDescriptorDacl().GetAceCount() == 2 class UmaskTest(TempDirTestCase): @@ -156,17 +156,17 @@ class UmaskTest(TempDirTestCase): try: dir1 = os.path.join(self.tempdir, 'probe1') filesystem.mkdir(dir1) - self.assertIs(filesystem.check_mode(dir1, 0o755), True) + assert filesystem.check_mode(dir1, 0o755) is True filesystem.umask(0o077) dir2 = os.path.join(self.tempdir, 'dir2') filesystem.mkdir(dir2) - self.assertIs(filesystem.check_mode(dir2, 0o700), True) + assert filesystem.check_mode(dir2, 0o700) is True dir3 = os.path.join(self.tempdir, 'dir3') filesystem.mkdir(dir3, mode=0o777) - self.assertIs(filesystem.check_mode(dir3, 0o700), True) + assert filesystem.check_mode(dir3, 0o700) is True finally: filesystem.umask(previous_umask) @@ -176,17 +176,17 @@ class UmaskTest(TempDirTestCase): try: file1 = os.path.join(self.tempdir, 'probe1') UmaskTest._create_file(file1) - self.assertIs(filesystem.check_mode(file1, 0o755), True) + assert filesystem.check_mode(file1, 0o755) is True filesystem.umask(0o077) file2 = os.path.join(self.tempdir, 'probe2') UmaskTest._create_file(file2) - self.assertIs(filesystem.check_mode(file2, 0o700), True) + assert filesystem.check_mode(file2, 0o700) is True file3 = os.path.join(self.tempdir, 'probe3') UmaskTest._create_file(file3) - self.assertIs(filesystem.check_mode(file3, 0o700), True) + assert filesystem.check_mode(file3, 0o700) is True finally: filesystem.umask(previous_umask) @@ -212,10 +212,10 @@ class ComputePrivateKeyModeTest(TempDirTestCase): if POSIX_MODE: # On Linux RWX permissions for group and R permission for world # are persisted from the existing moe - self.assertEqual(new_mode, 0o674) + assert new_mode == 0o674 else: # On Windows no permission is persisted - self.assertEqual(new_mode, 0o600) + assert new_mode == 0o600 @unittest.skipIf(POSIX_MODE, reason='Tests specific to Windows security') @@ -229,8 +229,8 @@ class WindowsOpenTest(TempDirTestCase): dacl = _get_security_dacl(path).GetSecurityDescriptorDacl() everybody = win32security.ConvertStringSidToSid(EVERYBODY_SID) - self.assertFalse([dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) - if dacl.GetAce(index)[2] == everybody]) + assert not [dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) + if dacl.GetAce(index)[2] == everybody] def test_existing_file_correct_permissions(self): path = os.path.join(self.tempdir, 'file') @@ -242,17 +242,17 @@ class WindowsOpenTest(TempDirTestCase): dacl = _get_security_dacl(path).GetSecurityDescriptorDacl() everybody = win32security.ConvertStringSidToSid(EVERYBODY_SID) - self.assertFalse([dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) - if dacl.GetAce(index)[2] == everybody]) + assert not [dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) + if dacl.GetAce(index)[2] == everybody] def test_create_file_on_open(self): # os.O_CREAT | os.O_EXCL + file not exists = OK self._test_one_creation(1, file_exist=False, flags=(os.O_CREAT | os.O_EXCL)) # os.O_CREAT | os.O_EXCL + file exists = EEXIST OS exception - with self.assertRaises(OSError) as raised: + with pytest.raises(OSError) as exc_info: self._test_one_creation(2, file_exist=True, flags=(os.O_CREAT | os.O_EXCL)) - self.assertEqual(raised.exception.errno, errno.EEXIST) + assert exc_info.value.errno == errno.EEXIST # os.O_CREAT + file not exists = OK self._test_one_creation(3, file_exist=False, flags=os.O_CREAT) @@ -265,14 +265,14 @@ class WindowsOpenTest(TempDirTestCase): open(path, 'w').close() filelock = lock.LockFile(path) try: - with self.assertRaises(OSError) as raised: + with pytest.raises(OSError) as exc_info: self._test_one_creation(5, file_exist=True, flags=os.O_CREAT) - self.assertEqual(raised.exception.errno, errno.EACCES) + assert exc_info.value.errno == errno.EACCES finally: filelock.release() # os.O_CREAT not set + file not exists = OS exception - with self.assertRaises(OSError): + with pytest.raises(OSError): self._test_one_creation(6, file_exist=False, flags=os.O_RDONLY) def _test_one_creation(self, num, file_exist, flags): @@ -298,20 +298,20 @@ class TempUmaskTests(test_util.TempDirTestCase): def test_works_normally(self): filesystem.umask(0o0022) - self.assertEqual(self._check_umask(), 0o0022) + assert self._check_umask() == 0o0022 with filesystem.temp_umask(0o0077): - self.assertEqual(self._check_umask(), 0o0077) - self.assertEqual(self._check_umask(), 0o0022) + assert self._check_umask() == 0o0077 + assert self._check_umask() == 0o0022 def test_resets_umask_after_exception(self): filesystem.umask(0o0022) - self.assertEqual(self._check_umask(), 0o0022) + assert self._check_umask() == 0o0022 try: with filesystem.temp_umask(0o0077): - self.assertEqual(self._check_umask(), 0o0077) + assert self._check_umask() == 0o0077 raise Exception() except: - self.assertEqual(self._check_umask(), 0o0022) + assert self._check_umask() == 0o0022 @unittest.skipIf(POSIX_MODE, reason='Test specific to Windows security') @@ -325,8 +325,8 @@ class WindowsMkdirTests(test_util.TempDirTestCase): everybody = win32security.ConvertStringSidToSid(EVERYBODY_SID) dacl = _get_security_dacl(path).GetSecurityDescriptorDacl() - self.assertFalse([dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) - if dacl.GetAce(index)[2] == everybody]) + assert not [dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) + if dacl.GetAce(index)[2] == everybody] def test_makedirs_correct_permissions(self): path = os.path.join(self.tempdir, 'dir') @@ -337,8 +337,8 @@ class WindowsMkdirTests(test_util.TempDirTestCase): everybody = win32security.ConvertStringSidToSid(EVERYBODY_SID) dacl = _get_security_dacl(subpath).GetSecurityDescriptorDacl() - self.assertFalse([dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) - if dacl.GetAce(index)[2] == everybody]) + assert not [dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) + if dacl.GetAce(index)[2] == everybody] def test_makedirs_switch_os_mkdir(self): path = os.path.join(self.tempdir, 'dir') @@ -346,13 +346,13 @@ class WindowsMkdirTests(test_util.TempDirTestCase): original_mkdir = std_os.mkdir filesystem.makedirs(path) - self.assertEqual(original_mkdir, std_os.mkdir) + assert original_mkdir == std_os.mkdir try: filesystem.makedirs(path) # Will fail because path already exists except OSError: pass - self.assertEqual(original_mkdir, std_os.mkdir) + assert original_mkdir == std_os.mkdir class MakedirsTests(test_util.TempDirTestCase): @@ -390,19 +390,19 @@ class CopyOwnershipAndModeTest(test_util.TempDirTestCase): filesystem.copy_ownership_and_apply_mode( 'dummy', self.probe_path, 0o700, copy_user=True, copy_group=False) - self.assertEqual(mock_set.call_count, 2) + assert mock_set.call_count == 2 first_call = mock_set.call_args_list[0] security = first_call[0][2] - self.assertEqual(system, security.GetSecurityDescriptorOwner()) + assert system == security.GetSecurityDescriptorOwner() second_call = mock_set.call_args_list[1] security = second_call[0][2] dacl = security.GetSecurityDescriptorDacl() everybody = win32security.ConvertStringSidToSid(EVERYBODY_SID) - self.assertTrue(dacl.GetAceCount()) - self.assertFalse([dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) - if dacl.GetAce(index)[2] == everybody]) + assert dacl.GetAceCount() + assert not [dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) + if dacl.GetAce(index)[2] == everybody] @unittest.skipUnless(POSIX_MODE, reason='Test specific to Linux security') def test_copy_ownership_and_apply_mode_linux(self): @@ -424,7 +424,7 @@ class CopyOwnershipAndModeTest(test_util.TempDirTestCase): util.safe_open(path1, 'w').close() util.safe_open(path2, 'w').close() - self.assertIs(filesystem.has_same_ownership(path1, path2), True) + assert filesystem.has_same_ownership(path1, path2) is True @unittest.skipIf(POSIX_MODE, reason='Test specific to Windows security') def test_copy_ownership_and_mode_windows(self): @@ -432,8 +432,8 @@ class CopyOwnershipAndModeTest(test_util.TempDirTestCase): dst = _create_probe(self.tempdir, name='dst') filesystem.chmod(src, 0o700) - self.assertIs(filesystem.check_mode(src, 0o700), True) - self.assertIs(filesystem.check_mode(dst, 0o744), True) + assert filesystem.check_mode(src, 0o700) is True + assert filesystem.check_mode(dst, 0o744) is True # Checking an actual change of owner is tricky during a unit test, since we do not know # if any user exists beside the current one. So we mock _copy_win_ownership. It's behavior @@ -442,7 +442,7 @@ class CopyOwnershipAndModeTest(test_util.TempDirTestCase): filesystem.copy_ownership_and_mode(src, dst) mock_copy_owner.assert_called_once_with(src, dst) - self.assertIs(filesystem.check_mode(dst, 0o700), True) + assert filesystem.check_mode(dst, 0o700) is True class CheckPermissionsTest(test_util.TempDirTestCase): @@ -452,14 +452,14 @@ class CheckPermissionsTest(test_util.TempDirTestCase): self.probe_path = _create_probe(self.tempdir) def test_check_mode(self): - self.assertIs(filesystem.check_mode(self.probe_path, 0o744), True) + assert filesystem.check_mode(self.probe_path, 0o744) is True filesystem.chmod(self.probe_path, 0o700) - self.assertFalse(filesystem.check_mode(self.probe_path, 0o744)) + assert not filesystem.check_mode(self.probe_path, 0o744) @unittest.skipIf(POSIX_MODE, reason='Test specific to Windows security') def test_check_owner_windows(self): - self.assertIs(filesystem.check_owner(self.probe_path), True) + assert filesystem.check_owner(self.probe_path) is True system = win32security.ConvertStringSidToSid(SYSTEM_SID) security = win32security.SECURITY_ATTRIBUTES().SECURITY_DESCRIPTOR @@ -467,11 +467,11 @@ class CheckPermissionsTest(test_util.TempDirTestCase): with mock.patch('win32security.GetFileSecurity') as mock_get: mock_get.return_value = security - self.assertFalse(filesystem.check_owner(self.probe_path)) + assert not filesystem.check_owner(self.probe_path) @unittest.skipUnless(POSIX_MODE, reason='Test specific to Linux security') def test_check_owner_linux(self): - self.assertIs(filesystem.check_owner(self.probe_path), True) + assert filesystem.check_owner(self.probe_path) is True import os as std_os # pylint: disable=os-module-forbidden @@ -481,35 +481,35 @@ class CheckPermissionsTest(test_util.TempDirTestCase): with mock.patch('os.getuid') as mock_uid: mock_uid.return_value = uid + 1 - self.assertFalse(filesystem.check_owner(self.probe_path)) + assert not filesystem.check_owner(self.probe_path) def test_check_permissions(self): - self.assertIs(filesystem.check_permissions(self.probe_path, 0o744), True) + assert filesystem.check_permissions(self.probe_path, 0o744) is True with mock.patch('certbot.compat.filesystem.check_mode') as mock_mode: mock_mode.return_value = False - self.assertFalse(filesystem.check_permissions(self.probe_path, 0o744)) + assert not filesystem.check_permissions(self.probe_path, 0o744) with mock.patch('certbot.compat.filesystem.check_owner') as mock_owner: mock_owner.return_value = False - self.assertFalse(filesystem.check_permissions(self.probe_path, 0o744)) + assert not filesystem.check_permissions(self.probe_path, 0o744) def test_check_min_permissions(self): filesystem.chmod(self.probe_path, 0o744) - self.assertIs(filesystem.has_min_permissions(self.probe_path, 0o744), True) + assert filesystem.has_min_permissions(self.probe_path, 0o744) is True filesystem.chmod(self.probe_path, 0o700) - self.assertFalse(filesystem.has_min_permissions(self.probe_path, 0o744)) + assert not filesystem.has_min_permissions(self.probe_path, 0o744) filesystem.chmod(self.probe_path, 0o741) - self.assertFalse(filesystem.has_min_permissions(self.probe_path, 0o744)) + assert not filesystem.has_min_permissions(self.probe_path, 0o744) def test_is_world_reachable(self): filesystem.chmod(self.probe_path, 0o744) - self.assertIs(filesystem.has_world_permissions(self.probe_path), True) + assert filesystem.has_world_permissions(self.probe_path) is True filesystem.chmod(self.probe_path, 0o700) - self.assertFalse(filesystem.has_world_permissions(self.probe_path)) + assert not filesystem.has_world_permissions(self.probe_path) class OsReplaceTest(test_util.TempDirTestCase): @@ -524,8 +524,8 @@ class OsReplaceTest(test_util.TempDirTestCase): # On Windows, a direct call to os.rename would fail because dst already exists. filesystem.replace(src, dst) - self.assertFalse(os.path.exists(src)) - self.assertIs(os.path.exists(dst), True) + assert not os.path.exists(src) + assert os.path.exists(dst) is True class RealpathTest(test_util.TempDirTestCase): @@ -541,8 +541,8 @@ class RealpathTest(test_util.TempDirTestCase): link_path = os.path.join(self.tempdir, 'link_abs') os.symlink(self.probe_path, link_path) - self.assertEqual(self.probe_path, filesystem.realpath(self.probe_path)) - self.assertEqual(self.probe_path, filesystem.realpath(link_path)) + assert self.probe_path == filesystem.realpath(self.probe_path) + assert self.probe_path == filesystem.realpath(link_path) # Relative resolution curdir = os.getcwd() @@ -552,8 +552,8 @@ class RealpathTest(test_util.TempDirTestCase): os.chdir(os.path.dirname(self.probe_path)) os.symlink(probe_name, link_path) - self.assertEqual(self.probe_path, filesystem.realpath(probe_name)) - self.assertEqual(self.probe_path, filesystem.realpath(link_path)) + assert self.probe_path == filesystem.realpath(probe_name) + assert self.probe_path == filesystem.realpath(link_path) finally: os.chdir(curdir) @@ -565,9 +565,8 @@ class RealpathTest(test_util.TempDirTestCase): os.symlink(link2_path, link3_path) os.symlink(link3_path, link1_path) - with self.assertRaises(RuntimeError) as error: + with pytest.raises(RuntimeError, match='link1 is a loop!') as error: filesystem.realpath(link1_path) - self.assertIn('link1 is a loop!', str(error.exception)) class IsExecutableTest(test_util.TempDirTestCase): @@ -595,7 +594,7 @@ class IsExecutableTest(test_util.TempDirTestCase): with mock.patch("certbot.compat.filesystem._generate_dacl", side_effect=_execute_mock): os.close(filesystem.open(file_path, os.O_CREAT | os.O_WRONLY, 0o666)) - self.assertFalse(filesystem.is_executable(file_path)) + assert not filesystem.is_executable(file_path) @mock.patch("certbot.compat.filesystem.os.path.isfile") @mock.patch("certbot.compat.filesystem.os.access") @@ -603,7 +602,7 @@ class IsExecutableTest(test_util.TempDirTestCase): with _fix_windows_runtime(): mock_access.return_value = True mock_isfile.return_value = True - self.assertIs(filesystem.is_executable("/path/to/exe"), True) + assert filesystem.is_executable("/path/to/exe") is True @mock.patch("certbot.compat.filesystem.os.path.isfile") @mock.patch("certbot.compat.filesystem.os.access") @@ -611,7 +610,7 @@ class IsExecutableTest(test_util.TempDirTestCase): with _fix_windows_runtime(): mock_access.return_value = True mock_isfile.return_value = True - self.assertIs(filesystem.is_executable("exe"), True) + assert filesystem.is_executable("exe") is True @mock.patch("certbot.compat.filesystem.os.path.isfile") @mock.patch("certbot.compat.filesystem.os.access") @@ -619,7 +618,7 @@ class IsExecutableTest(test_util.TempDirTestCase): with _fix_windows_runtime(): mock_access.return_value = True mock_isfile.return_value = False - self.assertFalse(filesystem.is_executable("exe")) + assert not filesystem.is_executable("exe") class ReadlinkTest(unittest.TestCase): @@ -627,25 +626,25 @@ class ReadlinkTest(unittest.TestCase): @mock.patch("certbot.compat.filesystem.os.readlink") def test_path_posix(self, mock_readlink): mock_readlink.return_value = "/normal/path" - self.assertEqual(filesystem.readlink("dummy"), "/normal/path") + assert filesystem.readlink("dummy") == "/normal/path" @unittest.skipIf(POSIX_MODE, reason='Tests specific to Windows') @mock.patch("certbot.compat.filesystem.os.readlink") def test_normal_path_windows(self, mock_readlink): # Python <3.8 mock_readlink.return_value = "C:\\short\\path" - self.assertEqual(filesystem.readlink("dummy"), "C:\\short\\path") + assert filesystem.readlink("dummy") == "C:\\short\\path" # Python >=3.8 (os.readlink always returns the extended form) mock_readlink.return_value = "\\\\?\\C:\\short\\path" - self.assertEqual(filesystem.readlink("dummy"), "C:\\short\\path") + assert filesystem.readlink("dummy") == "C:\\short\\path" @unittest.skipIf(POSIX_MODE, reason='Tests specific to Windows') @mock.patch("certbot.compat.filesystem.os.readlink") def test_extended_path_windows(self, mock_readlink): # Following path is largely over the 260 characters permitted in the normal form. mock_readlink.return_value = "\\\\?\\C:\\long" + 1000 * "\\path" - with self.assertRaises(ValueError): + with pytest.raises(ValueError): filesystem.readlink("dummy") @contextlib.contextmanager diff --git a/certbot/tests/compat/misc_test.py b/certbot/tests/compat/misc_test.py index 5668e0718..ff9c2a003 100644 --- a/certbot/tests/compat/misc_test.py +++ b/certbot/tests/compat/misc_test.py @@ -24,7 +24,7 @@ class ExecuteStatusTest(unittest.TestCase): mock_run.return_value.stderr = stderr mock_run.return_value.returncode = returncode with mock.patch("certbot.compat.misc.logger") as mock_logger: - self.assertEqual(self._call(given_name, given_command), (returncode, stderr, stdout)) + assert self._call(given_name, given_command) == (returncode, stderr, stdout) executed_command = mock_run.call_args[1].get( "args", mock_run.call_args[0][0]) @@ -32,8 +32,8 @@ class ExecuteStatusTest(unittest.TestCase): expected_command = ['powershell.exe', '-Command', given_command] else: expected_command = given_command - self.assertEqual(executed_command, expected_command) - self.assertEqual(executed_command, expected_command) + assert executed_command == expected_command + assert executed_command == expected_command mock_logger.info.assert_any_call("Running %s command: %s", given_name, given_command) diff --git a/certbot/tests/compat/os_test.py b/certbot/tests/compat/os_test.py index 844492678..673e50f9e 100644 --- a/certbot/tests/compat/os_test.py +++ b/certbot/tests/compat/os_test.py @@ -13,10 +13,12 @@ class OsTest(unittest.TestCase): # Checks for os module for method in ['chmod', 'chown', 'open', 'mkdir', 'makedirs', 'rename', 'replace', 'access', 'stat', 'fstat']: - self.assertRaises(RuntimeError, getattr(os, method)) + with pytest.raises(RuntimeError): + getattr(os, method)() # Checks for os.path module for method in ['realpath']: - self.assertRaises(RuntimeError, getattr(os.path, method)) + with pytest.raises(RuntimeError): + getattr(os.path, method)() if __name__ == "__main__": diff --git a/certbot/tests/configuration_test.py b/certbot/tests/configuration_test.py index 1d860ea0d..9482aec2f 100644 --- a/certbot/tests/configuration_test.py +++ b/certbot/tests/configuration_test.py @@ -26,20 +26,21 @@ class NamespaceConfigTest(test_util.ConfigTestCase): def test_init_same_ports(self): self.config.namespace.https_port = 4321 from certbot.configuration import NamespaceConfig - self.assertRaises(errors.Error, NamespaceConfig, self.config.namespace) + with pytest.raises(errors.Error): + NamespaceConfig(self.config.namespace) def test_proxy_getattr(self): - self.assertEqual(self.config.foo, 'bar') - self.assertEqual(self.config.work_dir, os.path.join(self.tempdir, 'work')) + assert self.config.foo == 'bar' + assert self.config.work_dir == os.path.join(self.tempdir, 'work') def test_server_path(self): - self.assertEqual(['acme-server.org:443', 'new'], - self.config.server_path.split(os.path.sep)) + assert ['acme-server.org:443', 'new'] == \ + self.config.server_path.split(os.path.sep) self.config.namespace.server = ('http://user:pass@acme.server:443' '/p/a/t/h;parameters?query#fragment') - self.assertEqual(['user:pass@acme.server:443', 'p', 'a', 't', 'h'], - self.config.server_path.split(os.path.sep)) + assert ['user:pass@acme.server:443', 'p', 'a', 't', 'h'] == \ + self.config.server_path.split(os.path.sep) @mock.patch('certbot.configuration.constants') def test_dynamic_dirs(self, mock_constants): @@ -53,26 +54,20 @@ class NamespaceConfigTest(test_util.ConfigTestCase): ref_path = misc.underscores_for_unsupported_characters_in_path( 'acc/acme-server.org:443/new') - self.assertEqual( - os.path.normpath(self.config.accounts_dir), - os.path.normpath(os.path.join(self.config.config_dir, ref_path))) - self.assertEqual( - os.path.normpath(self.config.backup_dir), - os.path.normpath(os.path.join(self.config.work_dir, 'backups'))) + assert os.path.normpath(self.config.accounts_dir) == \ + os.path.normpath(os.path.join(self.config.config_dir, ref_path)) + assert os.path.normpath(self.config.backup_dir) == \ + os.path.normpath(os.path.join(self.config.work_dir, 'backups')) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) - self.assertEqual( - os.path.normpath(self.config.csr_dir), - os.path.normpath(os.path.join(self.config.config_dir, 'csr'))) - self.assertEqual( - os.path.normpath(self.config.key_dir), - os.path.normpath(os.path.join(self.config.config_dir, 'keys'))) - self.assertEqual( - os.path.normpath(self.config.in_progress_dir), - os.path.normpath(os.path.join(self.config.work_dir, '../p'))) - self.assertEqual( - os.path.normpath(self.config.temp_checkpoint_dir), - os.path.normpath(os.path.join(self.config.work_dir, 't'))) + assert os.path.normpath(self.config.csr_dir) == \ + os.path.normpath(os.path.join(self.config.config_dir, 'csr')) + assert os.path.normpath(self.config.key_dir) == \ + os.path.normpath(os.path.join(self.config.config_dir, 'keys')) + assert os.path.normpath(self.config.in_progress_dir) == \ + os.path.normpath(os.path.join(self.config.work_dir, '../p')) + assert 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 @@ -92,23 +87,23 @@ class NamespaceConfigTest(test_util.ConfigTestCase): mock_namespace.server = server config = NamespaceConfig(mock_namespace) - self.assertTrue(os.path.isabs(config.config_dir)) - self.assertEqual(config.config_dir, - os.path.join(os.getcwd(), config_base)) - self.assertTrue(os.path.isabs(config.work_dir)) - self.assertEqual(config.work_dir, - os.path.join(os.getcwd(), work_base)) - self.assertTrue(os.path.isabs(config.logs_dir)) - self.assertEqual(config.logs_dir, - os.path.join(os.getcwd(), logs_base)) - self.assertTrue(os.path.isabs(config.accounts_dir)) - self.assertTrue(os.path.isabs(config.backup_dir)) + assert os.path.isabs(config.config_dir) + assert config.config_dir == \ + os.path.join(os.getcwd(), config_base) + assert os.path.isabs(config.work_dir) + assert config.work_dir == \ + os.path.join(os.getcwd(), work_base) + assert os.path.isabs(config.logs_dir) + assert config.logs_dir == \ + os.path.join(os.getcwd(), logs_base) + assert os.path.isabs(config.accounts_dir) + assert os.path.isabs(config.backup_dir) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) - self.assertTrue(os.path.isabs(config.csr_dir)) - self.assertTrue(os.path.isabs(config.key_dir)) - self.assertTrue(os.path.isabs(config.in_progress_dir)) - self.assertTrue(os.path.isabs(config.temp_checkpoint_dir)) + assert os.path.isabs(config.csr_dir) + assert os.path.isabs(config.key_dir) + assert os.path.isabs(config.in_progress_dir) + assert os.path.isabs(config.temp_checkpoint_dir) @mock.patch('certbot.configuration.constants') def test_renewal_dynamic_dirs(self, mock_constants): @@ -116,13 +111,10 @@ class NamespaceConfigTest(test_util.ConfigTestCase): mock_constants.LIVE_DIR = 'l' mock_constants.RENEWAL_CONFIGS_DIR = 'renewal_configs' - self.assertEqual( - self.config.default_archive_dir, os.path.join(self.config.config_dir, 'a')) - self.assertEqual( - self.config.live_dir, os.path.join(self.config.config_dir, 'l')) - self.assertEqual( - self.config.renewal_configs_dir, os.path.join( - self.config.config_dir, 'renewal_configs')) + assert self.config.default_archive_dir == os.path.join(self.config.config_dir, 'a') + assert self.config.live_dir == os.path.join(self.config.config_dir, 'l') + assert self.config.renewal_configs_dir == os.path.join( + self.config.config_dir, 'renewal_configs') def test_renewal_absolute_paths(self): from certbot.configuration import NamespaceConfig @@ -140,29 +132,29 @@ class NamespaceConfigTest(test_util.ConfigTestCase): mock_namespace.logs_dir = logs_base config = NamespaceConfig(mock_namespace) - self.assertTrue(os.path.isabs(config.default_archive_dir)) - self.assertTrue(os.path.isabs(config.live_dir)) - self.assertTrue(os.path.isabs(config.renewal_configs_dir)) + assert os.path.isabs(config.default_archive_dir) + assert os.path.isabs(config.live_dir) + assert os.path.isabs(config.renewal_configs_dir) def test_get_and_set_attr(self): self.config.foo = 42 - self.assertEqual(self.config.namespace.foo, 42) + assert self.config.namespace.foo == 42 self.config.namespace.bar = 1337 - self.assertEqual(self.config.bar, 1337) + assert self.config.bar == 1337 def test_hook_directories(self): - self.assertEqual(self.config.renewal_hooks_dir, + assert self.config.renewal_hooks_dir == \ os.path.join(self.config.config_dir, - constants.RENEWAL_HOOKS_DIR)) - self.assertEqual(self.config.renewal_pre_hooks_dir, + constants.RENEWAL_HOOKS_DIR) + assert self.config.renewal_pre_hooks_dir == \ os.path.join(self.config.renewal_hooks_dir, - constants.RENEWAL_PRE_HOOKS_DIR)) - self.assertEqual(self.config.renewal_deploy_hooks_dir, + constants.RENEWAL_PRE_HOOKS_DIR) + assert self.config.renewal_deploy_hooks_dir == \ os.path.join(self.config.renewal_hooks_dir, - constants.RENEWAL_DEPLOY_HOOKS_DIR)) - self.assertEqual(self.config.renewal_post_hooks_dir, + constants.RENEWAL_DEPLOY_HOOKS_DIR) + assert self.config.renewal_post_hooks_dir == \ os.path.join(self.config.renewal_hooks_dir, - constants.RENEWAL_POST_HOOKS_DIR)) + constants.RENEWAL_POST_HOOKS_DIR) if __name__ == '__main__': diff --git a/certbot/tests/crypto_util_test.py b/certbot/tests/crypto_util_test.py index 141588d81..49efef4ea 100644 --- a/certbot/tests/crypto_util_test.py +++ b/certbot/tests/crypto_util_test.py @@ -1,5 +1,6 @@ """Tests for certbot.crypto_util.""" import logging +import re import sys import unittest from unittest import mock @@ -54,14 +55,15 @@ class GenerateKeyTest(test_util.TempDirTestCase): def test_success(self, mock_make): mock_make.return_value = b'key_pem' key = self._call(1024, self.workdir) - self.assertEqual(key.pem, b'key_pem') - self.assertIn('key-certbot.pem', key.file) - self.assertTrue(os.path.exists(os.path.join(self.workdir, key.file))) + assert key.pem == b'key_pem' + assert 'key-certbot.pem' in key.file + assert os.path.exists(os.path.join(self.workdir, key.file)) @mock.patch('certbot.crypto_util.make_key') def test_key_failure(self, mock_make): mock_make.side_effect = ValueError - self.assertRaises(ValueError, self._call, 431, self.workdir) + with pytest.raises(ValueError): + self._call(431, self.workdir) class GenerateCSRTest(test_util.TempDirTestCase): @@ -76,8 +78,8 @@ class GenerateCSRTest(test_util.TempDirTestCase): csr = generate_csr( mock.Mock(pem='dummy_key'), 'example.com', self.tempdir, strict_permissions=True) - self.assertEqual(csr.data, b'csr_pem') - self.assertIn('csr-certbot.pem', csr.file) + assert csr.data == b'csr_pem' + assert 'csr-certbot.pem' in csr.file class ValidCSRTest(unittest.TestCase): @@ -89,19 +91,19 @@ class ValidCSRTest(unittest.TestCase): return valid_csr(csr) def test_valid_pem_true(self): - self.assertTrue(self._call(test_util.load_vector('csr_512.pem'))) + assert self._call(test_util.load_vector('csr_512.pem')) def test_valid_pem_san_true(self): - self.assertTrue(self._call(test_util.load_vector('csr-san_512.pem'))) + assert self._call(test_util.load_vector('csr-san_512.pem')) def test_valid_der_false(self): - self.assertFalse(self._call(test_util.load_vector('csr_512.der'))) + assert not self._call(test_util.load_vector('csr_512.der')) def test_empty_false(self): - self.assertFalse(self._call('')) + assert not self._call('') def test_random_false(self): - self.assertFalse(self._call('foo bar')) + assert not self._call('foo bar') class CSRMatchesPubkeyTest(unittest.TestCase): @@ -113,12 +115,12 @@ class CSRMatchesPubkeyTest(unittest.TestCase): return csr_matches_pubkey(*args, **kwargs) def test_valid_true(self): - self.assertTrue(self._call( - test_util.load_vector('csr_512.pem'), RSA512_KEY)) + assert self._call( + test_util.load_vector('csr_512.pem'), RSA512_KEY) def test_invalid_false(self): - self.assertFalse(self._call( - test_util.load_vector('csr_512.pem'), RSA256_KEY)) + assert not self._call( + test_util.load_vector('csr_512.pem'), RSA256_KEY) class ImportCSRFileTest(unittest.TestCase): @@ -134,29 +136,27 @@ class ImportCSRFileTest(unittest.TestCase): data = test_util.load_vector('csr_512.der') data_pem = test_util.load_vector('csr_512.pem') - self.assertEqual( - (OpenSSL.crypto.FILETYPE_PEM, + assert (OpenSSL.crypto.FILETYPE_PEM, util.CSR(file=csrfile, data=data_pem, form="pem"), - ["Example.com"]), - self._call(csrfile, data)) + ["Example.com"]) == \ + self._call(csrfile, data) def test_pem_csr(self): csrfile = test_util.vector_path('csr_512.pem') data = test_util.load_vector('csr_512.pem') - self.assertEqual( - (OpenSSL.crypto.FILETYPE_PEM, + assert (OpenSSL.crypto.FILETYPE_PEM, util.CSR(file=csrfile, data=data, form="pem"), - ["Example.com"],), - self._call(csrfile, data)) + ["Example.com"],) == \ + self._call(csrfile, data) def test_bad_csr(self): - self.assertRaises(errors.Error, self._call, - test_util.vector_path('cert_512.pem'), + with pytest.raises(errors.Error): + self._call(test_util.vector_path('cert_512.pem'), test_util.load_vector('cert_512.pem')) @@ -179,42 +179,28 @@ class MakeKeyTest(unittest.TestCase): OpenSSL.crypto.FILETYPE_PEM, make_key(elliptic_curve=name, key_type='ecdsa') ) - self.assertEqual(pkey.bits(), bits) + assert pkey.bits() == bits def test_bad_key_sizes(self): from certbot.crypto_util import make_key # Try a bad key size for RSA and ECDSA - with self.assertRaises(errors.Error) as e: + with pytest.raises(errors.Error, match='Unsupported RSA key length: 512'): make_key(bits=512, key_type='rsa') - self.assertEqual( - "Unsupported RSA key length: 512", - str(e.exception), - "Unsupported RSA key length: 512" - ) def test_bad_elliptic_curve_name(self): from certbot.crypto_util import make_key - with self.assertRaises(errors.Error) as e: + with pytest.raises(errors.Error, match='Unsupported elliptic curve: nothere'): make_key(elliptic_curve="nothere", key_type='ecdsa') - self.assertEqual( - "Unsupported elliptic curve: nothere", - str(e.exception), - "Unsupported elliptic curve: nothere" - ) def test_bad_key_type(self): from certbot.crypto_util import make_key # Try a bad --key-type - with self.assertRaises(errors.Error) as e: + with pytest.raises(errors.Error, + match=re.escape('Invalid key_type specified: unf. Use [rsa|ecdsa]')): OpenSSL.crypto.load_privatekey( OpenSSL.crypto.FILETYPE_PEM, make_key(1024, key_type='unf')) - self.assertEqual( - "Invalid key_type specified: unf. Use [rsa|ecdsa]", - str(e.exception), - "Invalid key_type specified: unf. Use [rsa|ecdsa]", - ) class VerifyCertSetup(unittest.TestCase): @@ -241,11 +227,12 @@ class VerifyRenewableCertTest(VerifyCertSetup): return verify_renewable_cert(renewable_cert) def test_verify_renewable_cert(self): - self.assertIsNone(self._call(self.renewable_cert)) + assert self._call(self.renewable_cert) is None @mock.patch('certbot.crypto_util.verify_renewable_cert_sig', side_effect=errors.Error("")) def test_verify_renewable_cert_failure(self, unused_verify_renewable_cert_sign): - self.assertRaises(errors.Error, self._call, self.bad_renewable_cert) + with pytest.raises(errors.Error): + self._call(self.bad_renewable_cert) class VerifyRenewableCertSigTest(VerifyCertSetup): @@ -256,18 +243,19 @@ class VerifyRenewableCertSigTest(VerifyCertSetup): return verify_renewable_cert_sig(renewable_cert) def test_cert_sig_match(self): - self.assertIsNone(self._call(self.renewable_cert)) + assert self._call(self.renewable_cert) is None def test_cert_sig_match_ec(self): renewable_cert = mock.MagicMock() renewable_cert.cert_path = P256_CERT_PATH renewable_cert.chain_path = P256_CERT_PATH renewable_cert.key_path = P256_KEY - self.assertIsNone(self._call(renewable_cert)) + assert self._call(renewable_cert) is None def test_cert_sig_mismatch(self): self.bad_renewable_cert.cert_path = test_util.vector_path('cert_512_bad.pem') - self.assertRaises(errors.Error, self._call, self.bad_renewable_cert) + with pytest.raises(errors.Error): + self._call(self.bad_renewable_cert) class VerifyFullchainTest(VerifyCertSetup): @@ -278,14 +266,16 @@ class VerifyFullchainTest(VerifyCertSetup): return verify_fullchain(renewable_cert) def test_fullchain_matches(self): - self.assertIsNone(self._call(self.renewable_cert)) + assert self._call(self.renewable_cert) is None def test_fullchain_mismatch(self): - self.assertRaises(errors.Error, self._call, self.bad_renewable_cert) + with pytest.raises(errors.Error): + self._call(self.bad_renewable_cert) def test_fullchain_ioerror(self): self.bad_renewable_cert.chain = "dog" - self.assertRaises(errors.Error, self._call, self.bad_renewable_cert) + with pytest.raises(errors.Error): + self._call(self.bad_renewable_cert) class VerifyCertMatchesPrivKeyTest(VerifyCertSetup): @@ -298,13 +288,14 @@ class VerifyCertMatchesPrivKeyTest(VerifyCertSetup): def test_cert_priv_key_match(self): self.renewable_cert.cert = SS_CERT_PATH self.renewable_cert.privkey = RSA2048_KEY_PATH - self.assertIsNone(self._call(self.renewable_cert)) + assert self._call(self.renewable_cert) is None def test_cert_priv_key_mismatch(self): self.bad_renewable_cert.privkey = RSA256_KEY_PATH self.bad_renewable_cert.cert = SS_CERT_PATH - self.assertRaises(errors.Error, self._call, self.bad_renewable_cert) + with pytest.raises(errors.Error): + self._call(self.bad_renewable_cert) class ValidPrivkeyTest(unittest.TestCase): @@ -316,13 +307,13 @@ class ValidPrivkeyTest(unittest.TestCase): return valid_privkey(privkey) def test_valid_true(self): - self.assertTrue(self._call(RSA512_KEY)) + assert self._call(RSA512_KEY) def test_empty_false(self): - self.assertFalse(self._call('')) + assert not self._call('') def test_random_false(self): - self.assertFalse(self._call('foo bar')) + assert not self._call('foo bar') class GetSANsFromCertTest(unittest.TestCase): @@ -334,12 +325,11 @@ class GetSANsFromCertTest(unittest.TestCase): return get_sans_from_cert(*args, **kwargs) def test_single(self): - self.assertEqual([], self._call(test_util.load_vector('cert_512.pem'))) + assert [] == self._call(test_util.load_vector('cert_512.pem')) def test_san(self): - self.assertEqual( - ['example.com', 'www.example.com'], - self._call(test_util.load_vector('cert-san_512.pem'))) + assert ['example.com', 'www.example.com'] == \ + self._call(test_util.load_vector('cert-san_512.pem')) class GetNamesFromCertTest(unittest.TestCase): @@ -351,24 +341,22 @@ class GetNamesFromCertTest(unittest.TestCase): return get_names_from_cert(*args, **kwargs) def test_single(self): - self.assertEqual( - ['example.com'], - self._call(test_util.load_vector('cert_512.pem'))) + assert ['example.com'] == \ + self._call(test_util.load_vector('cert_512.pem')) def test_san(self): - self.assertEqual( - ['example.com', 'www.example.com'], - self._call(test_util.load_vector('cert-san_512.pem'))) + assert ['example.com', 'www.example.com'] == \ + self._call(test_util.load_vector('cert-san_512.pem')) def test_common_name_sans_order(self): # Tests that the common name comes first # followed by the SANS in alphabetical order - self.assertEqual( - ['example.com'] + ['{0}.example.com'.format(c) for c in 'abcd'], - self._call(test_util.load_vector('cert-5sans_512.pem'))) + assert ['example.com'] + ['{0}.example.com'.format(c) for c in 'abcd'] == \ + self._call(test_util.load_vector('cert-5sans_512.pem')) def test_parse_non_cert(self): - self.assertRaises(OpenSSL.crypto.Error, self._call, "hello there") + with pytest.raises(OpenSSL.crypto.Error): + self._call("hello there") class GetNamesFromReqTest(unittest.TestCase): @@ -380,26 +368,22 @@ class GetNamesFromReqTest(unittest.TestCase): return get_names_from_req(*args, **kwargs) def test_nonames(self): - self.assertEqual( - [], - self._call(test_util.load_vector('csr-nonames_512.pem'))) + assert [] == \ + self._call(test_util.load_vector('csr-nonames_512.pem')) def test_nosans(self): - self.assertEqual( - ['example.com'], - self._call(test_util.load_vector('csr-nosans_512.pem'))) + assert ['example.com'] == \ + self._call(test_util.load_vector('csr-nosans_512.pem')) def test_sans(self): - self.assertEqual( - ['example.com', 'example.org', 'example.net', 'example.info', - 'subdomain.example.com', 'other.subdomain.example.com'], - self._call(test_util.load_vector('csr-6sans_512.pem'))) + assert ['example.com', 'example.org', 'example.net', 'example.info', + 'subdomain.example.com', 'other.subdomain.example.com'] == \ + self._call(test_util.load_vector('csr-6sans_512.pem')) def test_der(self): from OpenSSL.crypto import FILETYPE_ASN1 - self.assertEqual( - ['Example.com'], - self._call(test_util.load_vector('csr_512.der'), typ=FILETYPE_ASN1)) + assert ['Example.com'] == \ + self._call(test_util.load_vector('csr_512.der'), typ=FILETYPE_ASN1) class CertLoaderTest(unittest.TestCase): @@ -409,14 +393,14 @@ class CertLoaderTest(unittest.TestCase): from certbot.crypto_util import pyopenssl_load_certificate cert, file_type = pyopenssl_load_certificate(CERT) - self.assertEqual(cert.digest('sha256'), - OpenSSL.crypto.load_certificate(file_type, CERT).digest('sha256')) + assert cert.digest('sha256') == \ + OpenSSL.crypto.load_certificate(file_type, CERT).digest('sha256') def test_load_invalid_cert(self): from certbot.crypto_util import pyopenssl_load_certificate bad_cert_data = CERT.replace(b"BEGIN CERTIFICATE", b"ASDFASDFASDF!!!") - self.assertRaises( - errors.Error, pyopenssl_load_certificate, bad_cert_data) + with pytest.raises(errors.Error): + pyopenssl_load_certificate(bad_cert_data) class NotBeforeTest(unittest.TestCase): @@ -424,8 +408,8 @@ class NotBeforeTest(unittest.TestCase): def test_notBefore(self): from certbot.crypto_util import notBefore - self.assertEqual(notBefore(CERT_PATH).isoformat(), - '2014-12-11T22:34:45+00:00') + assert notBefore(CERT_PATH).isoformat() == \ + '2014-12-11T22:34:45+00:00' class NotAfterTest(unittest.TestCase): @@ -433,16 +417,16 @@ class NotAfterTest(unittest.TestCase): def test_notAfter(self): from certbot.crypto_util import notAfter - self.assertEqual(notAfter(CERT_PATH).isoformat(), - '2014-12-18T22:34:45+00:00') + assert notAfter(CERT_PATH).isoformat() == \ + '2014-12-18T22:34:45+00:00' 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), - '914ffed8daf9e2c99d90ac95c77d54f32cbd556672facac380f0c063498df84e') + assert sha256sum(CERT_PATH) == \ + '914ffed8daf9e2c99d90ac95c77d54f32cbd556672facac380f0c063498df84e' class CertAndChainFromFullchainTest(unittest.TestCase): @@ -470,10 +454,11 @@ class CertAndChainFromFullchainTest(unittest.TestCase): for fullchain in (fullchain_pem, spacey_fullchain_pem, crlf_fullchain_pem, acmev1_fullchain_pem): cert_out, chain_out = cert_and_chain_from_fullchain(fullchain) - self.assertEqual(cert_out, cert_pem) - self.assertEqual(chain_out, chain_pem) + assert cert_out == cert_pem + assert chain_out == chain_pem - self.assertRaises(errors.Error, cert_and_chain_from_fullchain, cert_pem) + with pytest.raises(errors.Error): + cert_and_chain_from_fullchain(cert_pem) class FindChainWithIssuerTest(unittest.TestCase): @@ -492,7 +477,7 @@ class FindChainWithIssuerTest(unittest.TestCase): """Correctly pick the chain based on the root's CN""" fullchains = self._all_fullchains() matched = self._call(fullchains, "Pebble Root CA 0cc6f0") - self.assertEqual(matched, fullchains[1]) + assert matched == fullchains[1] @mock.patch('certbot.crypto_util.logger.info') def test_intermediate_match(self, mock_info): @@ -504,14 +489,14 @@ class FindChainWithIssuerTest(unittest.TestCase): # function under test here doesn't care about that. fullchains[1] = fullchains[1] + CERT_ISSUER.decode() matched = self._call(fullchains, "Pebble Root CA 0cc6f0") - self.assertEqual(matched, fullchains[0]) + assert matched == fullchains[0] mock_info.assert_not_called() @mock.patch('certbot.crypto_util.logger.info') def test_no_match(self, mock_info): fullchains = self._all_fullchains() matched = self._call(fullchains, "non-existent issuer") - self.assertEqual(matched, fullchains[0]) + assert matched == fullchains[0] mock_info.assert_not_called() @mock.patch('certbot.crypto_util.logger.warning') @@ -519,7 +504,7 @@ class FindChainWithIssuerTest(unittest.TestCase): fullchains = self._all_fullchains() matched = self._call(fullchains, "non-existent issuer", warn_on_no_match=True) - self.assertEqual(matched, fullchains[0]) + assert matched == fullchains[0] mock_warning.assert_called_once_with("Certbot has been configured to prefer " "certificate chains with issuer '%s', but no chain from the CA matched " "this issuer. Using the default certificate chain instead.", diff --git a/certbot/tests/display/completer_test.py b/certbot/tests/display/completer_test.py index e4f2d758e..ef013d520 100644 --- a/certbot/tests/display/completer_test.py +++ b/certbot/tests/display/completer_test.py @@ -48,12 +48,12 @@ class CompleterTest(test_util.TempDirTestCase): for i in range(num_paths): completion = my_completer.complete(self.tempdir, i) - self.assertIn(completion, self.paths) + assert completion in self.paths self.paths.remove(completion) - self.assertEqual(len(self.paths), 0) + assert len(self.paths) == 0 completion = my_completer.complete(self.tempdir, num_paths) - self.assertIsNone(completion) + assert completion is None @unittest.skipIf('readline' not in sys.modules, reason='Not relevant if readline is not available.') @@ -75,8 +75,8 @@ class CompleterTest(test_util.TempDirTestCase): with completer.Completer(): pass - self.assertEqual(readline.get_completer(), original_completer) - self.assertEqual(readline.get_completer_delims(), original_delims) + assert readline.get_completer() == original_completer + assert readline.get_completer_delims() == original_delims @mock.patch('certbot._internal.display.completer.readline', autospec=True) def test_context_manager_libedit(self, mock_readline): @@ -96,7 +96,7 @@ class CompleterTest(test_util.TempDirTestCase): with completer.Completer(): pass - self.assertIs(mock_readline.parse_and_bind.called, True) + assert mock_readline.parse_and_bind.called is True def enable_tab_completion(unused_command): diff --git a/certbot/tests/display/internal_util_test.py b/certbot/tests/display/internal_util_test.py index 61ee8d281..7af3d5d2f 100644 --- a/certbot/tests/display/internal_util_test.py +++ b/certbot/tests/display/internal_util_test.py @@ -21,7 +21,7 @@ class WrapLinesTest(unittest.TestCase): "really really really really long line...".format('\n')) text = wrap_lines(msg) - self.assertEqual(text.count('\n'), 3) + assert text.count('\n') == 3 class PlaceParensTest(unittest.TestCase): @@ -31,11 +31,11 @@ class PlaceParensTest(unittest.TestCase): return parens_around_char(label) def test_single_letter(self): - self.assertEqual("(a)", self._call("a")) + assert "(a)" == self._call("a") def test_multiple(self): - self.assertEqual("(L)abel", self._call("Label")) - self.assertEqual("(y)es please", self._call("yes please")) + assert "(L)abel" == self._call("Label") + assert "(y)es please" == self._call("yes please") class InputWithTimeoutTest(unittest.TestCase): @@ -48,14 +48,15 @@ class InputWithTimeoutTest(unittest.TestCase): def test_eof(self): with tempfile.TemporaryFile("r+") as f: with mock.patch("certbot._internal.display.util.sys.stdin", new=f): - self.assertRaises(EOFError, self._call) + with pytest.raises(EOFError): + self._call() def test_input(self, prompt=None): expected = "foo bar" stdin = io.StringIO(expected + "\n") with mock.patch("certbot.compat.misc.select.select") as mock_select: mock_select.return_value = ([stdin], [], [],) - self.assertEqual(self._call(prompt), expected) + assert self._call(prompt) == expected @mock.patch("certbot._internal.display.util.sys.stdout") def test_input_with_prompt(self, mock_stdout): @@ -69,7 +70,8 @@ class InputWithTimeoutTest(unittest.TestCase): stdin.bind(('', 0)) stdin.listen(1) with mock.patch("certbot._internal.display.util.sys.stdin", stdin): - self.assertRaises(errors.Error, self._call, timeout=0.001) + with pytest.raises(errors.Error): + self._call(timeout=0.001) stdin.close() @@ -84,13 +86,13 @@ class SeparateListInputTest(unittest.TestCase): return separate_list_input(input_) def test_commas(self): - self.assertEqual(self._call("a,b,c,test"), self.exp) + assert self._call("a,b,c,test") == self.exp def test_spaces(self): - self.assertEqual(self._call("a b c test"), self.exp) + assert self._call("a b c test") == self.exp def test_both(self): - self.assertEqual(self._call("a, b, c, test"), self.exp) + assert self._call("a, b, c, test") == self.exp def test_mess(self): actual = [ @@ -100,7 +102,7 @@ class SeparateListInputTest(unittest.TestCase): ] for act in actual: - self.assertEqual(act, self.exp) + assert act == self.exp class SummarizeDomainListTest(unittest.TestCase): @@ -110,18 +112,18 @@ class SummarizeDomainListTest(unittest.TestCase): return summarize_domain_list(domains) def test_single_domain(self): - self.assertEqual("example.com", self._call(["example.com"])) + assert "example.com" == self._call(["example.com"]) def test_two_domains(self): - self.assertEqual("example.com and example.org", - self._call(["example.com", "example.org"])) + assert "example.com and example.org" == \ + self._call(["example.com", "example.org"]) def test_many_domains(self): - self.assertEqual("example.com and 2 more domains", - self._call(["example.com", "example.org", "a.example.com"])) + assert "example.com and 2 more domains" == \ + self._call(["example.com", "example.org", "a.example.com"]) def test_empty_domains(self): - self.assertEqual("", self._call([])) + assert "" == self._call([]) class DescribeACMEErrorTest(unittest.TestCase): @@ -134,18 +136,17 @@ class DescribeACMEErrorTest(unittest.TestCase): acme_messages.Error(typ=typ, title=title, detail=detail)) def test_title_and_detail(self): - self.assertEqual("Unacceptable CSR :: CSR contained unknown extensions", self._call()) + assert "Unacceptable CSR :: CSR contained unknown extensions" == self._call() def test_detail(self): - self.assertEqual("CSR contained unknown extensions", self._call(title=None)) + assert "CSR contained unknown extensions" == self._call(title=None) def test_description(self): - self.assertEqual(acme_messages.ERROR_CODES["badCSR"], self._call(title=None, detail=None)) + assert acme_messages.ERROR_CODES["badCSR"] == self._call(title=None, detail=None) def test_unknown_type(self): - self.assertEqual( - "urn:ietf:params:acme:error:unknownErrorType", - self._call(typ="urn:ietf:params:acme:error:unknownErrorType", title=None, detail=None)) + assert "urn:ietf:params:acme:error:unknownErrorType" == \ + self._call(typ="urn:ietf:params:acme:error:unknownErrorType", title=None, detail=None) if __name__ == "__main__": diff --git a/certbot/tests/display/obj_test.py b/certbot/tests/display/obj_test.py index d180d8059..be9bd3242 100644 --- a/certbot/tests/display/obj_test.py +++ b/certbot/tests/display/obj_test.py @@ -30,7 +30,7 @@ class FileOutputDisplayTest(unittest.TestCase): self.displayer.notification("message", False) string = self.mock_stdout.write.call_args[0][0] - self.assertIn("message", string) + assert "message" in string mock_logger.debug.assert_called_with("Notifying user: %s", "message") def test_notification_pause(self): @@ -38,146 +38,144 @@ class FileOutputDisplayTest(unittest.TestCase): with mock.patch(input_with_timeout, return_value="enter"): self.displayer.notification("message", force_interactive=True) - self.assertIn("message", self.mock_stdout.write.call_args[0][0]) + assert "message" in self.mock_stdout.write.call_args[0][0] def test_notification_noninteractive(self): self._force_noninteractive(self.displayer.notification, "message") string = self.mock_stdout.write.call_args[0][0] - self.assertIn("message", string) + assert "message" in string def test_notification_noninteractive2(self): # The main purpose of this test is to make sure we only call # logger.warning once which _force_noninteractive checks internally self._force_noninteractive(self.displayer.notification, "message") string = self.mock_stdout.write.call_args[0][0] - self.assertIn("message", string) + assert "message" in string - self.assertTrue(self.displayer.skipped_interaction) + assert self.displayer.skipped_interaction self._force_noninteractive(self.displayer.notification, "message2") string = self.mock_stdout.write.call_args[0][0] - self.assertIn("message2", string) + assert "message2" in string def test_notification_decoration(self): from certbot.compat import os self.displayer.notification("message", pause=False, decorate=False) string = self.mock_stdout.write.call_args[0][0] - self.assertEqual(string, "message" + os.linesep) + assert string == "message" + os.linesep self.displayer.notification("message2", pause=False) string = self.mock_stdout.write.call_args[0][0] - self.assertIn("- - - ", string) - self.assertIn("message2" + os.linesep, string) + assert "- - - " in string + assert "message2" + os.linesep in string @mock.patch("certbot._internal.display.obj." "FileDisplay._get_valid_int_ans") def test_menu(self, mock_ans): mock_ans.return_value = (display_util.OK, 1) ret = self.displayer.menu("message", CHOICES, force_interactive=True) - self.assertEqual(ret, (display_util.OK, 0)) + assert ret == (display_util.OK, 0) def test_menu_noninteractive(self): default = 0 result = self._force_noninteractive( self.displayer.menu, "msg", CHOICES, default=default) - self.assertEqual(result, (display_util.OK, default)) + assert result == (display_util.OK, default) def test_input_cancel(self): input_with_timeout = "certbot._internal.display.util.input_with_timeout" with mock.patch(input_with_timeout, return_value="c"): code, _ = self.displayer.input("message", force_interactive=True) - self.assertTrue(code, display_util.CANCEL) + assert code, display_util.CANCEL def test_input_normal(self): input_with_timeout = "certbot._internal.display.util.input_with_timeout" with mock.patch(input_with_timeout, return_value="domain.com"): code, input_ = self.displayer.input("message", force_interactive=True) - self.assertEqual(code, display_util.OK) - self.assertEqual(input_, "domain.com") + assert code == display_util.OK + assert input_ == "domain.com" def test_input_noninteractive(self): default = "foo" code, input_ = self._force_noninteractive( self.displayer.input, "message", default=default) - self.assertEqual(code, display_util.OK) - self.assertEqual(input_, default) + assert code == display_util.OK + assert input_ == default def test_input_assertion_fail(self): # If the call to util.assert_valid_call is commented out, an # error.Error is raised, otherwise, an AssertionError is raised. - self.assertRaises(Exception, self._force_noninteractive, - self.displayer.input, "message", cli_flag="--flag") + with pytest.raises(Exception): + self._force_noninteractive(self.displayer.input, "message", cli_flag="--flag") def test_input_assertion_fail2(self): with mock.patch("certbot.display.util.assert_valid_call"): - self.assertRaises(errors.Error, self._force_noninteractive, - self.displayer.input, "msg", cli_flag="--flag") + with pytest.raises(errors.Error): + self._force_noninteractive(self.displayer.input, "msg", cli_flag="--flag") def test_yesno(self): input_with_timeout = "certbot._internal.display.util.input_with_timeout" with mock.patch(input_with_timeout, return_value="Yes"): - self.assertTrue(self.displayer.yesno( - "message", force_interactive=True)) + assert self.displayer.yesno( + "message", force_interactive=True) with mock.patch(input_with_timeout, return_value="y"): - self.assertTrue(self.displayer.yesno( - "message", force_interactive=True)) + assert self.displayer.yesno( + "message", force_interactive=True) with mock.patch(input_with_timeout, side_effect=["maybe", "y"]): - self.assertTrue(self.displayer.yesno( - "message", force_interactive=True)) + assert self.displayer.yesno( + "message", force_interactive=True) with mock.patch(input_with_timeout, return_value="No"): - self.assertFalse(self.displayer.yesno( - "message", force_interactive=True)) + assert not self.displayer.yesno( + "message", force_interactive=True) with mock.patch(input_with_timeout, side_effect=["cancel", "n"]): - self.assertFalse(self.displayer.yesno( - "message", force_interactive=True)) + assert not self.displayer.yesno( + "message", force_interactive=True) with mock.patch(input_with_timeout, return_value="a"): - self.assertTrue(self.displayer.yesno( - "msg", yes_label="Agree", force_interactive=True)) + assert self.displayer.yesno( + "msg", yes_label="Agree", force_interactive=True) def test_yesno_noninteractive(self): - self.assertTrue(self._force_noninteractive( - self.displayer.yesno, "message", default=True)) + assert self._force_noninteractive( + self.displayer.yesno, "message", default=True) @mock.patch("certbot._internal.display.util.input_with_timeout") def test_checklist_valid(self, mock_input): mock_input.return_value = "2 1" code, tag_list = self.displayer.checklist( "msg", TAGS, force_interactive=True) - self.assertEqual( - (code, set(tag_list)), (display_util.OK, {"tag1", "tag2"})) + assert (code, set(tag_list)) == (display_util.OK, {"tag1", "tag2"}) @mock.patch("certbot._internal.display.util.input_with_timeout") def test_checklist_empty(self, mock_input): mock_input.return_value = "" code, tag_list = self.displayer.checklist("msg", TAGS, force_interactive=True) - self.assertEqual( - (code, set(tag_list)), (display_util.OK, {"tag1", "tag2", "tag3"})) + assert (code, set(tag_list)) == (display_util.OK, {"tag1", "tag2", "tag3"}) @mock.patch("certbot._internal.display.util.input_with_timeout") def test_checklist_miss_valid(self, mock_input): mock_input.side_effect = ["10", "tag1 please", "1"] ret = self.displayer.checklist("msg", TAGS, force_interactive=True) - self.assertEqual(ret, (display_util.OK, ["tag1"])) + assert ret == (display_util.OK, ["tag1"]) @mock.patch("certbot._internal.display.util.input_with_timeout") def test_checklist_miss_quit(self, mock_input): mock_input.side_effect = ["10", "c"] ret = self.displayer.checklist("msg", TAGS, force_interactive=True) - self.assertEqual(ret, (display_util.CANCEL, [])) + assert ret == (display_util.CANCEL, []) def test_checklist_noninteractive(self): default = TAGS code, input_ = self._force_noninteractive( self.displayer.checklist, "msg", TAGS, default=default) - self.assertEqual(code, display_util.OK) - self.assertEqual(input_, default) + assert code == display_util.OK + assert input_ == default def test_scrub_checklist_input_valid(self): # pylint: disable=protected-access @@ -194,7 +192,7 @@ class FileOutputDisplayTest(unittest.TestCase): for i, list_ in enumerate(indices): set_tags = set( self.displayer._scrub_checklist_input(list_, TAGS)) - self.assertEqual(set_tags, exp[i]) + assert set_tags == exp[i] @mock.patch("certbot._internal.display.util.input_with_timeout") def test_directory_select(self, mock_input): @@ -203,15 +201,15 @@ class FileOutputDisplayTest(unittest.TestCase): mock_input.return_value = user_input returned = self.displayer.directory_select(*args) - self.assertEqual(returned, (display_util.OK, user_input)) + assert returned == (display_util.OK, user_input) def test_directory_select_noninteractive(self): default = "/var/www/html" code, input_ = self._force_noninteractive( self.displayer.directory_select, "msg", default=default) - self.assertEqual(code, display_util.OK) - self.assertEqual(input_, default) + assert code == display_util.OK + assert input_ == default def _force_noninteractive(self, func, *args, **kwargs): skipped_interaction = self.displayer.skipped_interaction @@ -222,9 +220,9 @@ class FileOutputDisplayTest(unittest.TestCase): result = func(*args, **kwargs) if skipped_interaction: - self.assertIs(mock_logger.warning.called, False) + assert mock_logger.warning.called is False else: - self.assertEqual(mock_logger.warning.call_count, 1) + assert mock_logger.warning.call_count == 1 return result @@ -238,8 +236,7 @@ class FileOutputDisplayTest(unittest.TestCase): ["2", "o"] ] for list_ in indices: - self.assertEqual( - self.displayer._scrub_checklist_input(list_, TAGS), []) + assert self.displayer._scrub_checklist_input(list_, TAGS) == [] def test_print_menu(self): # pylint: disable=protected-access @@ -251,13 +248,11 @@ class FileOutputDisplayTest(unittest.TestCase): # pylint: disable=protected-access input_with_timeout = "certbot._internal.display.util.input_with_timeout" with mock.patch(input_with_timeout, return_value="1"): - self.assertEqual( - self.displayer._get_valid_int_ans(1), (display_util.OK, 1)) + assert self.displayer._get_valid_int_ans(1) == (display_util.OK, 1) ans = "2" with mock.patch(input_with_timeout, return_value=ans): - self.assertEqual( - self.displayer._get_valid_int_ans(3), - (display_util.OK, int(ans))) + assert self.displayer._get_valid_int_ans(3) == \ + (display_util.OK, int(ans)) def test_get_valid_int_ans_invalid(self): # pylint: disable=protected-access @@ -269,9 +264,8 @@ class FileOutputDisplayTest(unittest.TestCase): input_with_timeout = "certbot._internal.display.util.input_with_timeout" for ans in answers: with mock.patch(input_with_timeout, side_effect=ans): - self.assertEqual( - self.displayer._get_valid_int_ans(3), - (display_util.CANCEL, -1)) + assert self.displayer._get_valid_int_ans(3) == \ + (display_util.CANCEL, -1) class NoninteractiveDisplayTest(unittest.TestCase): @@ -285,51 +279,55 @@ class NoninteractiveDisplayTest(unittest.TestCase): self.displayer.notification("message", 10) string = self.mock_stdout.write.call_args[0][0] - self.assertIn("message", string) + assert "message" in string mock_logger.debug.assert_called_with("Notifying user: %s", "message") def test_notification_decoration(self): from certbot.compat import os self.displayer.notification("message", pause=False, decorate=False) string = self.mock_stdout.write.call_args[0][0] - self.assertEqual(string, "message" + os.linesep) + assert string == "message" + os.linesep self.displayer.notification("message2", pause=False) string = self.mock_stdout.write.call_args[0][0] - self.assertIn("- - - ", string) - self.assertIn("message2" + os.linesep, string) + assert "- - - " in string + assert "message2" + os.linesep in string def test_input(self): d = "an incomputable value" ret = self.displayer.input("message", default=d) - self.assertEqual(ret, (display_util.OK, d)) - self.assertRaises(errors.MissingCommandlineFlag, self.displayer.input, "message") + assert ret == (display_util.OK, d) + with pytest.raises(errors.MissingCommandlineFlag): + self.displayer.input("message") def test_menu(self): ret = self.displayer.menu("message", CHOICES, default=1) - self.assertEqual(ret, (display_util.OK, 1)) - self.assertRaises(errors.MissingCommandlineFlag, self.displayer.menu, "message", CHOICES) + assert ret == (display_util.OK, 1) + with pytest.raises(errors.MissingCommandlineFlag): + self.displayer.menu("message", CHOICES) def test_yesno(self): d = False ret = self.displayer.yesno("message", default=d) - self.assertEqual(ret, d) - self.assertRaises(errors.MissingCommandlineFlag, self.displayer.yesno, "message") + assert ret == d + with pytest.raises(errors.MissingCommandlineFlag): + self.displayer.yesno("message") def test_checklist(self): d = [1, 3] ret = self.displayer.checklist("message", TAGS, default=d) - self.assertEqual(ret, (display_util.OK, d)) - self.assertRaises(errors.MissingCommandlineFlag, self.displayer.checklist, "message", TAGS) + assert ret == (display_util.OK, d) + with pytest.raises(errors.MissingCommandlineFlag): + self.displayer.checklist("message", TAGS) def test_directory_select(self): default = "/var/www/html" expected = (display_util.OK, default) actual = self.displayer.directory_select("msg", default) - self.assertEqual(expected, actual) + assert expected == actual - self.assertRaises( - errors.MissingCommandlineFlag, self.displayer.directory_select, "msg") + with pytest.raises(errors.MissingCommandlineFlag): + self.displayer.directory_select("msg") if __name__ == "__main__": diff --git a/certbot/tests/display/ops_test.py b/certbot/tests/display/ops_test.py index ded89b245..3363bfe2b 100644 --- a/certbot/tests/display/ops_test.py +++ b/certbot/tests/display/ops_test.py @@ -32,8 +32,10 @@ class GetEmailTest(unittest.TestCase): def test_cancel_none(self, mock_get_utility): mock_input = mock_get_utility().input mock_input.return_value = (display_util.CANCEL, "foo@bar.baz") - self.assertRaises(errors.Error, self._call) - self.assertRaises(errors.Error, self._call, optional=False) + with pytest.raises(errors.Error): + self._call() + with pytest.raises(errors.Error): + self._call(optional=False) @test_util.patch_display_util() def test_ok_safe(self, mock_get_utility): @@ -41,7 +43,7 @@ class GetEmailTest(unittest.TestCase): mock_input.return_value = (display_util.OK, "foo@bar.baz") with mock.patch("certbot.display.ops.util.safe_email") as mock_safe_email: mock_safe_email.return_value = True - self.assertEqual(self._call(), "foo@bar.baz") + assert self._call() == "foo@bar.baz" @test_util.patch_display_util() def test_ok_not_safe(self, mock_get_utility): @@ -49,7 +51,7 @@ class GetEmailTest(unittest.TestCase): mock_input.return_value = (display_util.OK, "foo@bar.baz") with mock.patch("certbot.display.ops.util.safe_email") as mock_safe_email: mock_safe_email.side_effect = [False, True] - self.assertEqual(self._call(), "foo@bar.baz") + assert self._call() == "foo@bar.baz" @test_util.patch_display_util() def test_invalid_flag(self, mock_get_utility): @@ -59,9 +61,9 @@ class GetEmailTest(unittest.TestCase): with mock.patch("certbot.display.ops.util.safe_email") as mock_safe_email: mock_safe_email.return_value = True self._call() - self.assertNotIn(invalid_txt, mock_input.call_args[0][0]) + assert invalid_txt not in mock_input.call_args[0][0] self._call(invalid=True) - self.assertIn(invalid_txt, mock_input.call_args[0][0]) + assert invalid_txt in mock_input.call_args[0][0] @test_util.patch_display_util() def test_optional_flag(self, mock_get_utility): @@ -71,7 +73,7 @@ class GetEmailTest(unittest.TestCase): mock_safe_email.side_effect = [False, True] self._call(optional=False) for call in mock_input.call_args_list: - self.assertNotIn("--register-unsafely-without-email", call[0][0]) + assert "--register-unsafely-without-email" not in call[0][0] @test_util.patch_display_util() def test_optional_invalid_unsafe(self, mock_get_utility): @@ -81,7 +83,7 @@ class GetEmailTest(unittest.TestCase): with mock.patch("certbot.display.ops.util.safe_email") as mock_safe_email: mock_safe_email.side_effect = [False, True] self._call(invalid=True) - self.assertIn(invalid_txt, mock_input.call_args[0][0]) + assert invalid_txt in mock_input.call_args[0][0] class ChooseAccountTest(test_util.TempDirTestCase): @@ -114,17 +116,17 @@ class ChooseAccountTest(test_util.TempDirTestCase): @test_util.patch_display_util() def test_one(self, mock_util): mock_util().menu.return_value = (display_util.OK, 0) - self.assertEqual(self._call([self.acc1]), self.acc1) + assert self._call([self.acc1]) == self.acc1 @test_util.patch_display_util() def test_two(self, mock_util): mock_util().menu.return_value = (display_util.OK, 1) - self.assertEqual(self._call([self.acc1, self.acc2]), self.acc2) + assert self._call([self.acc1, self.acc2]) == self.acc2 @test_util.patch_display_util() def test_cancel(self, mock_util): mock_util().menu.return_value = (display_util.CANCEL, 1) - self.assertIsNone(self._call([self.acc1, self.acc2])) + assert self._call([self.acc1, self.acc2]) is None class GenHttpsNamesTest(unittest.TestCase): @@ -138,7 +140,7 @@ class GenHttpsNamesTest(unittest.TestCase): return _gen_https_names(domains) def test_zero(self): - self.assertEqual(self._call([]), "") + assert self._call([]) == "" def test_one(self): doms = [ @@ -146,7 +148,7 @@ class GenHttpsNamesTest(unittest.TestCase): "asllkjsadfljasdf.c", ] for dom in doms: - self.assertEqual(self._call([dom]), "https://%s" % dom) + assert self._call([dom]) == "https://%s" % dom def test_two(self): domains_list = [ @@ -154,24 +156,22 @@ class GenHttpsNamesTest(unittest.TestCase): ["paypal.google.facebook.live.com", "*.zombo.example.com"], ] for doms in domains_list: - self.assertEqual( - self._call(doms), - "https://{dom[0]} and https://{dom[1]}".format(dom=doms)) + assert self._call(doms) == \ + "https://{dom[0]} and https://{dom[1]}".format(dom=doms) def test_three(self): doms = ["a.org", "b.org", "c.org"] # We use an oxford comma - self.assertEqual( - self._call(doms), + assert self._call(doms) == \ "https://{dom[0]}, https://{dom[1]}, and https://{dom[2]}".format( - dom=doms)) + dom=doms) def test_four(self): doms = ["a.org", "b.org", "c.org", "d.org"] exp = ("https://{dom[0]}, https://{dom[1]}, https://{dom[2]}, " "and https://{dom[3]}".format(dom=doms)) - self.assertEqual(self._call(doms), exp) + assert self._call(doms) == exp class ChooseNamesTest(unittest.TestCase): @@ -188,12 +188,12 @@ class ChooseNamesTest(unittest.TestCase): @mock.patch("certbot.display.ops._choose_names_manually") def test_no_installer(self, mock_manual): self._call(None) - self.assertEqual(mock_manual.call_count, 1) + assert mock_manual.call_count == 1 @test_util.patch_display_util() def test_no_installer_cancel(self, mock_util): mock_util().input.return_value = (display_util.CANCEL, []) - self.assertEqual(self._call(None), []) + assert self._call(None) == [] @test_util.patch_display_util() def test_no_names_choose(self, mock_util): @@ -202,18 +202,18 @@ class ChooseNamesTest(unittest.TestCase): mock_util().input.return_value = (display_util.OK, domain) actual_doms = self._call(self.mock_install) - self.assertEqual(mock_util().input.call_count, 1) - self.assertEqual(actual_doms, [domain]) + assert mock_util().input.call_count == 1 + assert actual_doms == [domain] def test_sort_names_trivial(self): from certbot.display.ops import _sort_names #sort an empty list - self.assertEqual(_sort_names([]), []) + assert _sort_names([]) == [] #sort simple domains some_domains = ["ex.com", "zx.com", "ax.com"] - self.assertEqual(_sort_names(some_domains), ["ax.com", "ex.com", "zx.com"]) + assert _sort_names(some_domains) == ["ax.com", "ex.com", "zx.com"] #Sort subdomains of a single domain domain = ".ex.com" @@ -223,7 +223,7 @@ class ChooseNamesTest(unittest.TestCase): sorted_short = sorted(unsorted_short) sorted_long = [us + domain for us in sorted_short] - self.assertEqual(_sort_names(unsorted_long), sorted_long) + assert _sort_names(unsorted_long) == sorted_long def test_sort_names_many(self): from certbot.display.ops import _sort_names @@ -241,7 +241,7 @@ class ChooseNamesTest(unittest.TestCase): for domain in sorted(unsorted_domains): for short in sorted_short: sortd.append(short+domain) - self.assertEqual(_sort_names(to_sort), sortd) + assert _sort_names(to_sort) == sortd @test_util.patch_display_util() @@ -250,24 +250,24 @@ class ChooseNamesTest(unittest.TestCase): mock_util().checklist.return_value = (display_util.OK, ["example.com"]) names = self._call(self.mock_install) - self.assertEqual(names, ["example.com"]) - self.assertEqual(mock_util().checklist.call_count, 1) + assert names == ["example.com"] + assert mock_util().checklist.call_count == 1 @test_util.patch_display_util() def test_filter_namees_override_question(self, mock_util): self.mock_install.get_all_names.return_value = {"example.com"} mock_util().checklist.return_value = (display_util.OK, ["example.com"]) names = self._call(self.mock_install, "Custom") - self.assertEqual(names, ["example.com"]) - self.assertEqual(mock_util().checklist.call_count, 1) - self.assertEqual(mock_util().checklist.call_args[0][0], "Custom") + assert names == ["example.com"] + assert mock_util().checklist.call_count == 1 + assert mock_util().checklist.call_args[0][0] == "Custom" @test_util.patch_display_util() def test_filter_names_nothing_selected(self, mock_util): self.mock_install.get_all_names.return_value = {"example.com"} mock_util().checklist.return_value = (display_util.OK, []) - self.assertEqual(self._call(self.mock_install), []) + assert self._call(self.mock_install) == [] @test_util.patch_display_util() def test_filter_names_cancel(self, mock_util): @@ -275,7 +275,7 @@ class ChooseNamesTest(unittest.TestCase): mock_util().checklist.return_value = ( display_util.CANCEL, ["example.com"]) - self.assertEqual(self._call(self.mock_install), []) + assert self._call(self.mock_install) == [] def test_get_valid_domains(self): from certbot.display.ops import get_valid_domains @@ -284,9 +284,9 @@ class ChooseNamesTest(unittest.TestCase): "justtld", "*.wildcard.com"] all_invalid = ["öóòps.net", "uniçodé.com"] two_valid = ["example.com", "úniçøde.com", "also.example.com"] - self.assertEqual(get_valid_domains(all_valid), all_valid) - self.assertEqual(get_valid_domains(all_invalid), []) - self.assertEqual(len(get_valid_domains(two_valid)), 2) + assert get_valid_domains(all_valid) == all_valid + assert get_valid_domains(all_invalid) == [] + assert len(get_valid_domains(two_valid)) == 2 @test_util.patch_display_util() def test_choose_manually(self, mock_util): @@ -297,23 +297,23 @@ class ChooseNamesTest(unittest.TestCase): # IDN and no retry utility_mock.input.return_value = (display_util.OK, "uniçodé.com") - self.assertEqual(_choose_names_manually(), []) + assert _choose_names_manually() == [] # IDN exception with previous mocks with mock.patch( "certbot.display.ops.internal_display_util.separate_list_input" ) as mock_sli: unicode_error = UnicodeEncodeError('mock', u'', 0, 1, 'mock') mock_sli.side_effect = unicode_error - self.assertEqual(_choose_names_manually(), []) + assert _choose_names_manually() == [] # Valid domains utility_mock.input.return_value = (display_util.OK, ("example.com," "under_score.example.com," "justtld," "valid.example.com")) - self.assertEqual(_choose_names_manually(), + assert _choose_names_manually() == \ ["example.com", "under_score.example.com", - "justtld", "valid.example.com"]) + "justtld", "valid.example.com"] @test_util.patch_display_util() def test_choose_manually_retry(self, mock_util): @@ -324,7 +324,7 @@ class ChooseNamesTest(unittest.TestCase): "uniçodé.com") utility_mock.yesno.side_effect = [True, True, False] _choose_names_manually() - self.assertEqual(utility_mock.yesno.call_count, 3) + assert utility_mock.yesno.call_count == 3 class SuccessInstallationTest(unittest.TestCase): @@ -342,11 +342,11 @@ class SuccessInstallationTest(unittest.TestCase): self._call(names) - self.assertEqual(mock_notify.call_count, 1) + assert mock_notify.call_count == 1 arg = mock_notify.call_args_list[0][0][0] for name in names: - self.assertIn(name, arg) + assert name in arg class SuccessRenewalTest(unittest.TestCase): @@ -364,7 +364,7 @@ class SuccessRenewalTest(unittest.TestCase): self._call(names) - self.assertEqual(mock_notify.call_count, 1) + assert mock_notify.call_count == 1 class SuccessRevocationTest(unittest.TestCase): @@ -406,30 +406,29 @@ class ValidatorTests(unittest.TestCase): (display_util.OK, self.valid_input)] returned = ops.validated_input(self.__validator, "message", force_interactive=True) - self.assertEqual(ValidatorTests.__ERROR, mock_util().notification.call_args[0][0]) - self.assertEqual(returned, (display_util.OK, self.valid_input)) + assert ValidatorTests.__ERROR == mock_util().notification.call_args[0][0] + assert returned == (display_util.OK, self.valid_input) @test_util.patch_display_util() def test_input_validation_with_default(self, mock_util): mock_util().input.side_effect = [(display_util.OK, self.valid_input)] returned = ops.validated_input(self.__validator, "msg", default="other") - self.assertEqual(returned, (display_util.OK, self.valid_input)) + assert returned == (display_util.OK, self.valid_input) @test_util.patch_display_util() def test_input_validation_with_bad_default(self, mock_util): mock_util().input.side_effect = [(display_util.OK, self.valid_input)] - self.assertRaises(AssertionError, - ops.validated_input, - self.__validator, "msg", default="") + with pytest.raises(AssertionError): + ops.validated_input(self.__validator, "msg", default="") @test_util.patch_display_util() def test_input_cancel_with_validator(self, mock_util): mock_util().input.side_effect = [(display_util.CANCEL, "")] code, unused_raw = ops.validated_input(self.__validator, "message", force_interactive=True) - self.assertEqual(code, display_util.CANCEL) + assert code == display_util.CANCEL @test_util.patch_display_util() def test_directory_select_validation(self, mock_util): @@ -437,23 +436,22 @@ class ValidatorTests(unittest.TestCase): (display_util.OK, self.valid_directory)] returned = ops.validated_directory(self.__validator, "msg", force_interactive=True) - self.assertEqual(ValidatorTests.__ERROR, mock_util().notification.call_args[0][0]) - self.assertEqual(returned, (display_util.OK, self.valid_directory)) + assert ValidatorTests.__ERROR == mock_util().notification.call_args[0][0] + assert returned == (display_util.OK, self.valid_directory) @test_util.patch_display_util() def test_directory_select_validation_with_default(self, mock_util): mock_util().directory_select.side_effect = [(display_util.OK, self.valid_directory)] returned = ops.validated_directory(self.__validator, "msg", default="other") - self.assertEqual(returned, (display_util.OK, self.valid_directory)) + assert returned == (display_util.OK, self.valid_directory) @test_util.patch_display_util() def test_directory_select_validation_with_bad_default(self, mock_util): mock_util().directory_select.side_effect = [(display_util.OK, self.valid_directory)] - self.assertRaises(AssertionError, - ops.validated_directory, - self.__validator, "msg", default="") + with pytest.raises(AssertionError): + ops.validated_directory(self.__validator, "msg", default="") class ChooseValuesTest(unittest.TestCase): @@ -468,9 +466,9 @@ class ChooseValuesTest(unittest.TestCase): items = ["first", "second", "third"] mock_util().checklist.return_value = (display_util.OK, [items[2]]) result = self._call(items, None) - self.assertEqual(result, [items[2]]) - self.assertIs(mock_util().checklist.called, True) - self.assertEqual(mock_util().checklist.call_args[0][0], "") + assert result == [items[2]] + assert mock_util().checklist.called is True + assert mock_util().checklist.call_args[0][0] == "" @test_util.patch_display_util() def test_choose_names_success_question(self, mock_util): @@ -478,9 +476,9 @@ class ChooseValuesTest(unittest.TestCase): question = "Which one?" mock_util().checklist.return_value = (display_util.OK, [items[1]]) result = self._call(items, question) - self.assertEqual(result, [items[1]]) - self.assertIs(mock_util().checklist.called, True) - self.assertEqual(mock_util().checklist.call_args[0][0], question) + assert result == [items[1]] + assert mock_util().checklist.called is True + assert mock_util().checklist.call_args[0][0] == question @test_util.patch_display_util() def test_choose_names_user_cancel(self, mock_util): @@ -488,9 +486,9 @@ class ChooseValuesTest(unittest.TestCase): question = "Want to cancel?" mock_util().checklist.return_value = (display_util.CANCEL, []) result = self._call(items, question) - self.assertEqual(result, []) - self.assertIs(mock_util().checklist.called, True) - self.assertEqual(mock_util().checklist.call_args[0][0], question) + assert result == [] + assert mock_util().checklist.called is True + assert mock_util().checklist.call_args[0][0] == question @mock.patch('certbot.display.ops.logger') @@ -504,18 +502,18 @@ class ReportExecutedCommand(unittest.TestCase): def test_mixed_success(self, mock_notify, mock_logger): self._call("some-hook", 0, "Did a thing", "Some warning") - self.assertEqual(mock_logger.warning.call_count, 1) - self.assertEqual(mock_notify.call_count, 1) + assert mock_logger.warning.call_count == 1 + assert mock_notify.call_count == 1 def test_mixed_error(self, mock_notify, mock_logger): self._call("some-hook", -127, "Did a thing", "Some warning") - self.assertEqual(mock_logger.warning.call_count, 2) - self.assertEqual(mock_notify.call_count, 1) + assert mock_logger.warning.call_count == 2 + assert mock_notify.call_count == 1 def test_empty_success(self, mock_notify, mock_logger): self._call("some-hook", 0, "\n", " ") - self.assertEqual(mock_logger.warning.call_count, 0) - self.assertEqual(mock_notify.call_count, 0) + assert mock_logger.warning.call_count == 0 + assert mock_notify.call_count == 0 if __name__ == "__main__": sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/eff_test.py b/certbot/tests/eff_test.py index 3a13e2ff1..33694e17e 100644 --- a/certbot/tests/eff_test.py +++ b/certbot/tests/eff_test.py @@ -48,50 +48,50 @@ class PrepareSubscriptionTest(SubscriptionTest): self._call() actual = mock_notify.call_args[0][0] expected_part = "because you didn't provide an e-mail address" - self.assertIn(expected_part, actual) - self.assertIsNone(self.account.meta.register_to_eff) + assert expected_part in actual + assert self.account.meta.register_to_eff is None @test_util.patch_display_util() def test_will_not_subscribe_with_no_prompt(self, mock_get_utility): self.config.eff_email = False self._call() self._assert_no_get_utility_calls(mock_get_utility) - self.assertIsNone(self.account.meta.register_to_eff) + assert self.account.meta.register_to_eff is None @test_util.patch_display_util() def test_will_subscribe_with_no_prompt(self, mock_get_utility): self.config.eff_email = True self._call() self._assert_no_get_utility_calls(mock_get_utility) - self.assertEqual(self.account.meta.register_to_eff, self.config.email) + assert self.account.meta.register_to_eff == self.config.email @test_util.patch_display_util() def test_will_not_subscribe_with_prompt(self, mock_get_utility): mock_get_utility().yesno.return_value = False self._call() - self.assertFalse(mock_get_utility().add_message.called) + assert not mock_get_utility().add_message.called self._assert_correct_yesno_call(mock_get_utility) - self.assertIsNone(self.account.meta.register_to_eff) + assert self.account.meta.register_to_eff is None @test_util.patch_display_util() def test_will_subscribe_with_prompt(self, mock_get_utility): mock_get_utility().yesno.return_value = True self._call() - self.assertFalse(mock_get_utility().add_message.called) + assert not mock_get_utility().add_message.called self._assert_correct_yesno_call(mock_get_utility) - self.assertEqual(self.account.meta.register_to_eff, self.config.email) + assert self.account.meta.register_to_eff == self.config.email def _assert_no_get_utility_calls(self, mock_get_utility): - self.assertFalse(mock_get_utility().yesno.called) - self.assertFalse(mock_get_utility().add_message.called) + assert not mock_get_utility().yesno.called + assert not mock_get_utility().add_message.called def _assert_correct_yesno_call(self, mock_get_utility): - self.assertTrue(mock_get_utility().yesno.called) + assert mock_get_utility().yesno.called call_args, call_kwargs = mock_get_utility().yesno.call_args actual = call_args[0] expected_part = 'Electronic Frontier Foundation' - self.assertIn(expected_part, actual) - self.assertFalse(call_kwargs.get('default', True)) + assert expected_part in actual + assert not call_kwargs.get('default', True) class HandleSubscriptionTest(SubscriptionTest): @@ -103,14 +103,14 @@ class HandleSubscriptionTest(SubscriptionTest): @mock.patch('certbot._internal.eff.subscribe') def test_no_subscribe(self, mock_subscribe): self._call() - self.assertIs(mock_subscribe.called, False) + assert mock_subscribe.called is False @mock.patch('certbot._internal.eff.subscribe') def test_subscribe(self, mock_subscribe): self.account.meta = self.account.meta.update(register_to_eff=self.config.email) self._call() - self.assertTrue(mock_subscribe.called) - self.assertEqual(mock_subscribe.call_args[0][0], self.config.email) + assert mock_subscribe.called + assert mock_subscribe.call_args[0][0] == self.config.email class SubscribeTest(unittest.TestCase): @@ -133,20 +133,20 @@ class SubscribeTest(unittest.TestCase): self._check_post_call(mock_post) def _check_post_call(self, mock_post): - self.assertEqual(mock_post.call_count, 1) + assert mock_post.call_count == 1 call_args, call_kwargs = mock_post.call_args - self.assertEqual(call_args[0], constants.EFF_SUBSCRIBE_URI) + assert call_args[0] == constants.EFF_SUBSCRIBE_URI data = call_kwargs.get('data') - self.assertIsNotNone(data) - self.assertEqual(data.get('email'), self.email) + assert data is not None + assert data.get('email') == self.email def test_bad_status(self): self.json['status'] = False self._call() actual = self._get_reported_message() expected_part = 'because your e-mail address appears to be invalid.' - self.assertIn(expected_part, actual) + assert expected_part in actual def test_not_ok(self): self.response.ok = False @@ -154,30 +154,30 @@ class SubscribeTest(unittest.TestCase): self._call() actual = self._get_reported_message() unexpected_part = 'because' - self.assertNotIn(unexpected_part, actual) + assert unexpected_part not in actual def test_response_not_json(self): self.response.json.side_effect = ValueError() self._call() actual = self._get_reported_message() expected_part = 'problem' - self.assertIn(expected_part, actual) + assert expected_part in actual def test_response_json_missing_status_element(self): self.json.clear() self._call() actual = self._get_reported_message() expected_part = 'problem' - self.assertIn(expected_part, actual) + assert expected_part in actual def _get_reported_message(self): - self.assertTrue(self.mock_notify.called) + assert self.mock_notify.called return self.mock_notify.call_args[0][0] @test_util.patch_display_util() def test_subscribe(self, mock_get_utility): self._call() - self.assertIs(mock_get_utility.called, False) + assert mock_get_utility.called is False if __name__ == '__main__': diff --git a/certbot/tests/error_handler_test.py b/certbot/tests/error_handler_test.py index 799350f8c..30bd90150 100644 --- a/certbot/tests/error_handler_test.py +++ b/certbot/tests/error_handler_test.py @@ -63,7 +63,7 @@ class ErrorHandlerTest(unittest.TestCase): except ValueError: exception_raised = True - self.assertTrue(exception_raised) + assert exception_raised self.init_func.assert_called_once_with(*self.init_args, **self.init_kwargs) @@ -78,14 +78,14 @@ class ErrorHandlerTest(unittest.TestCase): should_be_42 *= 10 # check execution stopped when the signal was sent - self.assertEqual(42, should_be_42) + assert 42 == should_be_42 # assert signals were caught - self.assertEqual([self.signals[0]], signals_received) + assert [self.signals[0]] == signals_received # assert the error handling function was just called once self.init_func.assert_called_once_with(*self.init_args, **self.init_kwargs) for signum in self.signals: - self.assertEqual(init_signals[signum], signal.getsignal(signum)) + assert init_signals[signum] == signal.getsignal(signum) def test_bad_recovery(self): bad_func = mock.MagicMock(side_effect=[ValueError]) @@ -109,7 +109,7 @@ class ErrorHandlerTest(unittest.TestCase): with signal_receiver(self.signals) as signals_received: with self.handler: send_signal(sig2) - self.assertEqual([sig2, sig1], signals_received) + assert [sig2, sig1] == signals_received self.init_func.assert_called_once_with(*self.init_args, **self.init_kwargs) bad_func.assert_called_once_with() @@ -120,7 +120,7 @@ class ErrorHandlerTest(unittest.TestCase): sys.exit(0) except SystemExit: pass - self.assertIs(self.init_func.called, False) + assert self.init_func.called is False def test_regular_exit(self): func = mock.MagicMock() diff --git a/certbot/tests/errors_test.py b/certbot/tests/errors_test.py index b9decfd68..9432c7433 100644 --- a/certbot/tests/errors_test.py +++ b/certbot/tests/errors_test.py @@ -21,9 +21,9 @@ class FailedChallengesTest(unittest.TestCase): error=messages.Error.with_code("tls", detail="detail")))}) def test_str(self): - self.assertTrue(str(self.error).startswith( + assert str(self.error).startswith( "Failed authorization procedure. example.com (dns-01): " - "urn:ietf:params:acme:error:tls")) + "urn:ietf:params:acme:error:tls") def test_unicode(self): from certbot.errors import FailedChallenges @@ -33,9 +33,9 @@ class FailedChallengesTest(unittest.TestCase): chall=acme_util.DNS01, uri=None, error=messages.Error.with_code("tls", detail=arabic_detail)))}) - self.assertTrue(str(arabic_error).startswith( + assert str(arabic_error).startswith( "Failed authorization procedure. example.com (dns-01): " - "urn:ietf:params:acme:error:tls")) + "urn:ietf:params:acme:error:tls") class StandaloneBindErrorTest(unittest.TestCase): @@ -46,12 +46,12 @@ class StandaloneBindErrorTest(unittest.TestCase): self.error = StandaloneBindError(mock.sentinel.error, 1234) def test_instance_args(self): - self.assertEqual(mock.sentinel.error, self.error.socket_error) - self.assertEqual(1234, self.error.port) + assert mock.sentinel.error == self.error.socket_error + assert 1234 == self.error.port def test_str(self): - self.assertTrue(str(self.error).startswith( - "Problem binding to port 1234: ")) + assert str(self.error).startswith( + "Problem binding to port 1234: ") if __name__ == "__main__": diff --git a/certbot/tests/helpful_test.py b/certbot/tests/helpful_test.py index 6a60362d0..6a9b5e73f 100644 --- a/certbot/tests/helpful_test.py +++ b/certbot/tests/helpful_test.py @@ -17,58 +17,58 @@ class TestScanningFlags(unittest.TestCase): arg_parser = HelpfulArgumentParser(['run'], {}) detected_flag = arg_parser.prescan_for_flag('--help', ['all', 'certonly']) - self.assertIs(detected_flag, False) + assert detected_flag is False detected_flag = arg_parser.prescan_for_flag('-h', ['all, certonly']) - self.assertIs(detected_flag, False) + assert detected_flag is False def test_prescan_unvalid_topic(self): arg_parser = HelpfulArgumentParser(['--help', 'all'], {}) detected_flag = arg_parser.prescan_for_flag('--help', ['potato']) - self.assertIs(detected_flag, True) + assert detected_flag is True detected_flag = arg_parser.prescan_for_flag('-h', arg_parser.help_topics) - self.assertIs(detected_flag, False) + assert detected_flag is False def test_prescan_valid_topic(self): arg_parser = HelpfulArgumentParser(['-h', 'all'], {}) detected_flag = arg_parser.prescan_for_flag('-h', arg_parser.help_topics) - self.assertEqual(detected_flag, 'all') + assert detected_flag == 'all' detected_flag = arg_parser.prescan_for_flag('--help', arg_parser.help_topics) - self.assertIs(detected_flag, False) + assert detected_flag is False class TestDetermineVerbs(unittest.TestCase): '''Tests for determine_verb methods of HelpfulArgumentParser''' def test_determine_verb_wrong_verb(self): arg_parser = HelpfulArgumentParser(['potato'], {}) - self.assertEqual(arg_parser.verb, "run") - self.assertEqual(arg_parser.args, ["potato"]) + assert arg_parser.verb == "run" + assert arg_parser.args == ["potato"] def test_determine_verb_help(self): arg_parser = HelpfulArgumentParser(['--help', 'everything'], {}) - self.assertEqual(arg_parser.verb, "help") - self.assertEqual(arg_parser.args, ["--help", "everything"]) + assert arg_parser.verb == "help" + assert arg_parser.args == ["--help", "everything"] arg_parser = HelpfulArgumentParser(['-d', 'some_domain', '--help', 'all'], {}) - self.assertEqual(arg_parser.verb, "help") - self.assertEqual(arg_parser.args, ['-d', 'some_domain', '--help', - 'all']) + assert arg_parser.verb == "help" + assert arg_parser.args == ['-d', 'some_domain', '--help', + 'all'] def test_determine_verb(self): arg_parser = HelpfulArgumentParser(['certonly'], {}) - self.assertEqual(arg_parser.verb, 'certonly') - self.assertEqual(arg_parser.args, []) + assert arg_parser.verb == 'certonly' + assert arg_parser.args == [] arg_parser = HelpfulArgumentParser(['auth'], {}) - self.assertEqual(arg_parser.verb, 'certonly') - self.assertEqual(arg_parser.args, []) + assert arg_parser.verb == 'certonly' + assert arg_parser.args == [] arg_parser = HelpfulArgumentParser(['everything'], {}) - self.assertEqual(arg_parser.verb, 'run') - self.assertEqual(arg_parser.args, []) + assert arg_parser.verb == 'run' + assert arg_parser.args == [] class TestAdd(unittest.TestCase): @@ -78,8 +78,8 @@ class TestAdd(unittest.TestCase): arg_parser.add(None, "--hello-world") parsed_args = arg_parser.parser.parse_args(['--hello-world', 'Hello World!']) - self.assertIs(parsed_args.hello_world, 'Hello World!') - self.assertFalse(hasattr(parsed_args, 'potato')) + assert parsed_args.hello_world is 'Hello World!' + assert not hasattr(parsed_args, 'potato') def test_add_expected_argument(self): arg_parser = HelpfulArgumentParser(['--help', 'run'], {}) @@ -89,15 +89,16 @@ class TestAdd(unittest.TestCase): metavar="EAB_KID", help="Key Identifier for External Account Binding") parsed_args = arg_parser.parser.parse_args(["--eab-kid", None]) - self.assertIsNone(parsed_args.eab_kid) - self.assertTrue(hasattr(parsed_args, 'eab_kid')) + assert parsed_args.eab_kid is None + assert hasattr(parsed_args, 'eab_kid') class TestAddGroup(unittest.TestCase): '''Test add_group method of HelpfulArgumentParser''' def test_add_group_no_input(self): arg_parser = HelpfulArgumentParser(['run'], {}) - self.assertRaises(TypeError, arg_parser.add_group) + with pytest.raises(TypeError): + arg_parser.add_group() def test_add_group_topic_not_visible(self): # The user request help on run. A topic that given somewhere in the @@ -105,16 +106,16 @@ class TestAddGroup(unittest.TestCase): arg_parser = HelpfulArgumentParser(['--help', 'run'], {}) arg_parser.add_group("auth", description="description of auth") - self.assertEqual(arg_parser.groups, {}) + assert arg_parser.groups == {} def test_add_group_topic_requested_help(self): arg_parser = HelpfulArgumentParser(['--help', 'run'], {}) arg_parser.add_group("run", description="description of run") - self.assertTrue(arg_parser.groups["run"]) + assert arg_parser.groups["run"] arg_parser.add_group("certonly", description="description of certonly") - with self.assertRaises(KeyError): - self.assertIs(arg_parser.groups["certonly"], False) + with pytest.raises(KeyError): + assert arg_parser.groups["certonly"] is False class TestParseArgsErrors(unittest.TestCase): @@ -126,7 +127,7 @@ class TestParseArgsErrors(unittest.TestCase): arg_parser.add( None, constants.FORCE_INTERACTIVE_FLAG, action="store_true") - with self.assertRaises(errors.Error): + with pytest.raises(errors.Error): arg_parser.parse_args() def test_parse_args_non_interactive_and_force_interactive(self): @@ -139,7 +140,7 @@ class TestParseArgsErrors(unittest.TestCase): action="store_true" ) - with self.assertRaises(errors.Error): + with pytest.raises(errors.Error): arg_parser.parse_args() def test_parse_args_subset_names_wildcard_domain(self): @@ -189,7 +190,7 @@ class TestParseArgsErrors(unittest.TestCase): arg_parser.add(None, "--must-staple") arg_parser.add(None, "--validate-hooks") arg_parser.add(None, "--allow-subset-of-names") - with self.assertRaises(errors.Error): + with pytest.raises(errors.Error): arg_parser.parse_args() diff --git a/certbot/tests/hook_test.py b/certbot/tests/hook_test.py index 4260a0b30..de67d96ef 100644 --- a/certbot/tests/hook_test.py +++ b/certbot/tests/hook_test.py @@ -26,9 +26,9 @@ class ValidateHooksTest(unittest.TestCase): self._call(config) types = [call[0][1] for call in mock_validate_hook.call_args_list] - self.assertEqual({"pre", "post", "deploy",}, set(types[:-1])) + assert {"pre", "post", "deploy",} == set(types[:-1]) # This ensures error messages are about deploy hooks when appropriate - self.assertEqual("renew", types[-1]) + assert "renew" == types[-1] class ValidateHookTest(test_util.TempDirTestCase): @@ -46,19 +46,21 @@ class ValidateHookTest(test_util.TempDirTestCase): # to get a fully working test around executable permissions. See # certbot.tests.compat.filesystem::NotExecutableTest for more in-depth tests. with mock.patch("certbot._internal.hooks.filesystem.is_executable", return_value=False): - self.assertRaises(errors.HookCommandNotFound, self._call, 'dummy', "foo") + with pytest.raises(errors.HookCommandNotFound): + self._call('dummy', "foo") @mock.patch("certbot._internal.hooks.util.exe_exists") def test_not_found(self, mock_exe_exists): mock_exe_exists.return_value = False with mock.patch("certbot._internal.hooks.plug_util.path_surgery") as mock_ps: - self.assertRaises(errors.HookCommandNotFound, self._call, "foo", "bar") - self.assertTrue(mock_ps.called) + with pytest.raises(errors.HookCommandNotFound): + self._call("foo", "bar") + assert mock_ps.called @mock.patch("certbot._internal.hooks._prog") def test_unset(self, mock_prog): self._call(None, "foo") - self.assertIs(mock_prog.called, False) + assert mock_prog.called is False class HookTest(test_util.ConfigTestCase): @@ -131,8 +133,8 @@ class PreHookTest(HookTest): with mock.patch("certbot._internal.hooks.logger") as mock_logger: mock_execute = self._call_with_mock_execute(self.config) - self.assertIs(mock_execute.called, False) - self.assertIs(mock_logger.info.called, False) + assert mock_execute.called is False + assert mock_logger.info.called is False def test_renew_disabled_dir_hooks(self): self.config.directory_hooks = False @@ -157,8 +159,8 @@ class PreHookTest(HookTest): def _test_no_executions_common(self): with mock.patch("certbot._internal.hooks.logger") as mock_logger: mock_execute = self._call_with_mock_execute(self.config) - self.assertIs(mock_execute.called, False) - self.assertTrue(mock_logger.info.called) + assert mock_execute.called is False + assert mock_logger.info.called class PostHookTest(HookTest): @@ -194,14 +196,14 @@ class PostHookTest(HookTest): self.config.verb = verb mock_execute = self._call_with_mock_execute(self.config) mock_execute.assert_called_once_with("post-hook", self.config.post_hook, env=mock.ANY) - self.assertFalse(self._get_eventually()) + assert not self._get_eventually() def test_cert_only_and_run_without_hook(self): self.config.post_hook = None for verb in ("certonly", "run",): self.config.verb = verb - self.assertFalse(self._call_with_mock_execute(self.config).called) - self.assertFalse(self._get_eventually()) + assert not self._call_with_mock_execute(self.config).called + assert not self._get_eventually() def test_renew_disabled_dir_hooks(self): self.config.directory_hooks = False @@ -237,7 +239,7 @@ class PostHookTest(HookTest): for _ in range(2): self._call(self.config) - self.assertEqual(self._get_eventually(), expected) + assert self._get_eventually() == expected def _get_eventually(self): from certbot._internal.hooks import post_hooks @@ -269,7 +271,7 @@ class RunSavedPostHooksTest(HookTest): self.eventually: List[str] = [] def test_empty(self): - self.assertFalse(self._call_with_mock_execute_and_eventually().called) + assert not self._call_with_mock_execute_and_eventually().called def test_multiple(self): self.eventually = ["foo", "bar", "baz", "qux"] @@ -277,7 +279,7 @@ class RunSavedPostHooksTest(HookTest): calls = mock_execute.call_args_list for actual_call, expected_arg in zip(calls, self.eventually): - self.assertEqual(actual_call[0][1], expected_arg) + assert actual_call[0][1] == expected_arg def test_single(self): self.eventually = ["foo"] @@ -308,8 +310,8 @@ class RenewalHookTest(HookTest): :rtype: `tuple` of `str` """ - self.assertEqual(os.environ["RENEWED_DOMAINS"], " ".join(domains)) - self.assertEqual(os.environ["RENEWED_LINEAGE"], lineage) + assert os.environ["RENEWED_DOMAINS"] == " ".join(domains) + assert os.environ["RENEWED_LINEAGE"] == lineage return (0, "", "") with mock.patch("certbot.compat.misc.execute_command_status") as mock_execute: @@ -344,16 +346,16 @@ class DeployHookTest(RenewalHookTest): self.config.dry_run = True mock_execute = self._call_with_mock_execute( self.config, ["example.org"], "/foo/bar") - self.assertIs(mock_execute.called, False) - self.assertTrue(mock_logger.info.called) + assert mock_execute.called is False + assert mock_logger.info.called @mock.patch("certbot._internal.hooks.logger") def test_no_hook(self, mock_logger): self.config.deploy_hook = None mock_execute = self._call_with_mock_execute( self.config, ["example.org"], "/foo/bar") - self.assertIs(mock_execute.called, False) - self.assertIs(mock_logger.info.called, False) + assert mock_execute.called is False + assert mock_logger.info.called is False def test_success(self): domains = ["example.org", "example.net"] @@ -392,8 +394,8 @@ class RenewHookTest(RenewalHookTest): self.config.dry_run = True mock_execute = self._call_with_mock_execute( self.config, ["example.org"], "/foo/bar") - self.assertIs(mock_execute.called, False) - self.assertEqual(mock_logger.info.call_count, 2) + assert mock_execute.called is False + assert mock_logger.info.call_count == 2 def test_no_hooks(self): self.config.renew_hook = None @@ -402,8 +404,8 @@ class RenewHookTest(RenewalHookTest): with mock.patch("certbot._internal.hooks.logger") as mock_logger: mock_execute = self._call_with_mock_execute( self.config, ["example.org"], "/foo/bar") - self.assertIs(mock_execute.called, False) - self.assertIs(mock_logger.info.called, False) + assert mock_execute.called is False + assert mock_logger.info.called is False def test_overlap(self): self.config.renew_hook = self.dir_hook @@ -427,7 +429,7 @@ class ListHooksTest(test_util.TempDirTestCase): return list_hooks(*args, **kwargs) def test_empty(self): - self.assertFalse(self._call(self.tempdir)) + assert not self._call(self.tempdir) def test_multiple(self): names = sorted( @@ -437,19 +439,19 @@ class ListHooksTest(test_util.TempDirTestCase): for name in names: create_hook(name) - self.assertEqual(self._call(self.tempdir), names) + assert self._call(self.tempdir) == names def test_single(self): name = os.path.join(self.tempdir, "foo") create_hook(name) - self.assertEqual(self._call(self.tempdir), [name]) + assert self._call(self.tempdir) == [name] def test_ignore_tilde(self): name = os.path.join(self.tempdir, "foo~") create_hook(name) - self.assertEqual(self._call(self.tempdir), []) + assert self._call(self.tempdir) == [] def create_hook(file_path): diff --git a/certbot/tests/lock_test.py b/certbot/tests/lock_test.py index fd36bb225..0aec70b21 100644 --- a/certbot/tests/lock_test.py +++ b/certbot/tests/lock_test.py @@ -52,8 +52,8 @@ class LockFileTest(test_util.TempDirTestCase): args=(self.lock_path,)) child.start() child.join() - self.assertEqual(child.exitcode, 0) - self.assertTrue(os.path.exists(self.lock_path)) + assert child.exitcode == 0 + assert os.path.exists(self.lock_path) # Test we're still able to properly acquire and release the lock self.test_removed() @@ -68,7 +68,7 @@ class LockFileTest(test_util.TempDirTestCase): try: locked_repr = repr(lock_file) self._test_repr_common(lock_file, locked_repr) - self.assertIn('acquired', locked_repr) + assert 'acquired' in locked_repr finally: lock_file.release() @@ -77,11 +77,11 @@ class LockFileTest(test_util.TempDirTestCase): lock_file.release() released_repr = repr(lock_file) self._test_repr_common(lock_file, released_repr) - self.assertIn('released', released_repr) + assert 'released' in released_repr def _test_repr_common(self, lock_file, lock_repr): - self.assertIn(lock_file.__class__.__name__, lock_repr) - self.assertIn(self.lock_path, lock_repr) + assert lock_file.__class__.__name__ in lock_repr + assert self.lock_path in lock_repr @test_util.skip_on_windows( 'Race conditions on lock are specific to the non-blocking file access approach on Linux.') @@ -101,12 +101,12 @@ class LockFileTest(test_util.TempDirTestCase): with mock.patch('certbot._internal.lock.filesystem.os.stat') as mock_stat: mock_stat.side_effect = delete_and_stat self._call(self.lock_path) - self.assertEqual(len(should_delete), 0) + assert len(should_delete) == 0 def test_removed(self): lock_file = self._call(self.lock_path) lock_file.release() - self.assertFalse(os.path.exists(self.lock_path)) + assert not os.path.exists(self.lock_path) def test_unexpected_lockf_or_locking_err(self): if POSIX_MODE: @@ -119,7 +119,7 @@ class LockFileTest(test_util.TempDirTestCase): try: self._call(self.lock_path) except IOError as err: - self.assertIn(msg, str(err)) + assert msg in str(err) else: # pragma: no cover self.fail('IOError not raised') @@ -135,7 +135,7 @@ class LockFileTest(test_util.TempDirTestCase): try: self._call(self.lock_path) except OSError as err: - self.assertIn(msg, str(err)) + assert msg in str(err) else: # pragma: no cover self.fail('OSError not raised') diff --git a/certbot/tests/log_test.py b/certbot/tests/log_test.py index 4aaa9bcbd..338425505 100644 --- a/certbot/tests/log_test.py +++ b/certbot/tests/log_test.py @@ -44,7 +44,7 @@ class PreArgParseSetupTest(unittest.TestCase): mock_root_logger = mock_get() mock_root_logger.setLevel.assert_called_once_with(logging.DEBUG) - self.assertEqual(mock_root_logger.addHandler.call_count, 2) + assert mock_root_logger.addHandler.call_count == 2 memory_handler: Optional[logging.handlers.MemoryHandler] = None for call in mock_root_logger.addHandler.call_args_list: @@ -53,8 +53,8 @@ class PreArgParseSetupTest(unittest.TestCase): memory_handler = handler target = memory_handler.target else: - self.assertIsInstance(handler, logging.StreamHandler) - self.assertIsInstance(target, logging.StreamHandler) + assert isinstance(handler, logging.StreamHandler) + assert isinstance(target, logging.StreamHandler) mock_register.assert_called_once_with(logging.shutdown) mock_sys.excepthook(1, 2, 3) @@ -108,9 +108,9 @@ class PostArgParseSetupTest(test_util.ConfigTestCase): self.root_logger.removeHandler.assert_called_once_with( self.memory_handler) - self.assertTrue(self.root_logger.addHandler.called) - self.assertTrue(os.path.exists(log_path)) - self.assertFalse(os.path.exists(self.temp_path)) + assert self.root_logger.addHandler.called + assert os.path.exists(log_path) + assert not os.path.exists(self.temp_path) mock_sys.excepthook(1, 2, 3) mock_except_hook.assert_called_once_with( 1, 2, 3, debug=self.config.debug, @@ -118,9 +118,9 @@ class PostArgParseSetupTest(test_util.ConfigTestCase): level = self.stream_handler.level if self.config.quiet: - self.assertEqual(level, constants.QUIET_LOGGING_LEVEL) + assert level == constants.QUIET_LOGGING_LEVEL else: - self.assertEqual(level, constants.DEFAULT_LOGGING_LEVEL) + assert level == constants.DEFAULT_LOGGING_LEVEL def test_debug(self): self.config.debug = True @@ -150,7 +150,7 @@ class SetupLogFileHandlerTest(test_util.ConfigTestCase): try: self._call(self.config, 'test.log', '%(message)s') except errors.Error as err: - self.assertIn('--logs-dir', str(err)) + assert '--logs-dir' in str(err) else: # pragma: no cover self.fail('Error not raised.') @@ -166,20 +166,20 @@ class SetupLogFileHandlerTest(test_util.ConfigTestCase): handler, log_path = self._call(self.config, log_file, '%(message)s') handler.close() - self.assertEqual(handler.level, logging.DEBUG) - self.assertEqual(handler.formatter.converter, time.localtime) + assert handler.level == logging.DEBUG + assert handler.formatter.converter == time.localtime expected_path = os.path.join(self.config.logs_dir, log_file) - self.assertEqual(log_path, expected_path) + assert log_path == expected_path backup_path = os.path.join(self.config.logs_dir, log_file + '.1') - self.assertEqual(os.path.exists(backup_path), should_rollover) + assert os.path.exists(backup_path) == should_rollover @mock.patch('certbot._internal.log.logging.handlers.RotatingFileHandler') def test_max_log_backups_used(self, mock_handler): self._call(self.config, 'test.log', '%(message)s') backup_count = mock_handler.call_args[1]['backupCount'] - self.assertEqual(self.config.max_log_backups, backup_count) + assert self.config.max_log_backups == backup_count class ColoredStreamHandlerTest(unittest.TestCase): @@ -201,17 +201,17 @@ class ColoredStreamHandlerTest(unittest.TestCase): def test_format(self): msg = 'I did a thing' self.logger.debug(msg) - self.assertEqual(self.stream.getvalue(), '{0}\n'.format(msg)) + assert self.stream.getvalue() == '{0}\n'.format(msg) def test_format_and_red_level(self): msg = 'I did another thing' self.handler.red_level = logging.DEBUG self.logger.debug(msg) - self.assertEqual(self.stream.getvalue(), + assert self.stream.getvalue() == \ '{0}{1}{2}\n'.format(util.ANSI_SGR_RED, msg, - util.ANSI_SGR_RESET)) + util.ANSI_SGR_RESET) class MemoryHandlerTest(unittest.TestCase): @@ -234,13 +234,13 @@ class MemoryHandlerTest(unittest.TestCase): def test_flush(self): self._test_log_debug() self.handler.flush(force=True) - self.assertEqual(self.stream.getvalue(), self.msg + '\n') + assert self.stream.getvalue() == self.msg + '\n' def test_not_flushed(self): # By default, logging.ERROR messages and higher are flushed self.logger.critical(self.msg) self.handler.flush() - self.assertEqual(self.stream.getvalue(), '') + assert self.stream.getvalue() == '' def test_target_reset(self): self._test_log_debug() @@ -249,8 +249,8 @@ class MemoryHandlerTest(unittest.TestCase): new_stream_handler = logging.StreamHandler(new_stream) self.handler.setTarget(new_stream_handler) self.handler.flush(force=True) - self.assertEqual(self.stream.getvalue(), '') - self.assertEqual(new_stream.getvalue(), self.msg + '\n') + assert self.stream.getvalue() == '' + assert new_stream.getvalue() == self.msg + '\n' new_stream_handler.close() def _test_log_debug(self): @@ -268,16 +268,16 @@ class TempHandlerTest(unittest.TestCase): self.handler.close() def test_permissions(self): - self.assertTrue(filesystem.check_permissions(self.handler.path, 0o600)) + assert filesystem.check_permissions(self.handler.path, 0o600) def test_delete(self): self.handler.close() - self.assertFalse(os.path.exists(self.handler.path)) + assert not os.path.exists(self.handler.path) def test_no_delete(self): self.handler.emit(mock.MagicMock()) self.handler.close() - self.assertTrue(os.path.exists(self.handler.path)) + assert os.path.exists(self.handler.path) os.remove(self.handler.path) @@ -328,7 +328,7 @@ class PostArgParseExceptHookTest(unittest.TestCase): exc_type = ValueError mock_logger, output = self._test_common(exc_type, debug=True, quiet=True) self._assert_exception_logged(mock_logger.error, exc_type) - self.assertNotIn('See the logfile', output) + assert 'See the logfile' not in output def test_custom_error(self): exc_type = errors.PluginError @@ -347,7 +347,7 @@ class PostArgParseExceptHookTest(unittest.TestCase): mock_logger, output = self._test_common(get_acme_error, debug=False) self._assert_exception_logged(mock_logger.debug, messages.Error) self._assert_quiet_output(mock_logger, output) - self.assertNotIn(messages.ERROR_PREFIX, output) + assert messages.ERROR_PREFIX not in output def test_other_error(self): exc_type = ValueError @@ -387,22 +387,22 @@ class PostArgParseExceptHookTest(unittest.TestCase): return mock_logger, output def _assert_exception_logged(self, log_func, exc_type): - self.assertTrue(log_func.called) + assert log_func.called call_kwargs = log_func.call_args[1] - self.assertIn('exc_info', call_kwargs) + assert 'exc_info' in call_kwargs actual_exc_info = call_kwargs['exc_info'] expected_exc_info = (exc_type, mock.ANY, mock.ANY) - self.assertEqual(actual_exc_info, expected_exc_info) + assert actual_exc_info == expected_exc_info def _assert_logfile_output(self, output): - self.assertIn('See the logfile', output) - self.assertIn(self.log_path, output) + assert 'See the logfile' in output + assert self.log_path in output def _assert_quiet_output(self, mock_logger, output): - self.assertIs(mock_logger.exception.called, False) - self.assertTrue(mock_logger.debug.called) - self.assertIn(self.error_msg, output) + assert mock_logger.exception.called is False + assert mock_logger.debug.called + assert self.error_msg in output class ExitWithAdviceTest(test_util.TempDirTestCase): @@ -417,13 +417,13 @@ class ExitWithAdviceTest(test_util.TempDirTestCase): open(log_file, 'w').close() err_str = self._test_common(log_file) - self.assertNotIn('logfiles', err_str) - self.assertIn(log_file, err_str) + assert 'logfiles' not in err_str + assert log_file in err_str def test_log_dir(self): err_str = self._test_common(self.tempdir) - self.assertIn('logfiles', err_str) - self.assertIn(self.tempdir, err_str) + assert 'logfiles' in err_str + assert self.tempdir in err_str # pylint: disable=inconsistent-return-statements def _test_common(self, *args, **kwargs): diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index e8230d87e..f8f01e522 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -55,8 +55,8 @@ class TestHandleCerts(unittest.TestCase): mock_lineage.ensure_deployed.return_value = False # pylint: disable=protected-access ret = main._handle_identical_cert_request(mock.Mock(), mock_lineage) - self.assertEqual(ret, ("reinstall", mock_lineage)) - self.assertTrue(mock_handle_migration.called) + assert ret == ("reinstall", mock_lineage) + assert mock_handle_migration.called @mock.patch('certbot._internal.renewal.should_renew') @mock.patch("certbot.display.util.menu") @@ -69,9 +69,9 @@ class TestHandleCerts(unittest.TestCase): mock_should_renew.return_value = False ret = main._handle_identical_cert_request(mock.MagicMock(verb="run", reinstall=False), mock_lineage) - self.assertTrue(mock_handle_migration.called) - self.assertFalse(mock_menu.called) - self.assertEqual(ret, ("renew", mock_lineage)) + assert mock_handle_migration.called + assert not mock_menu.called + assert ret == ("renew", mock_lineage) @mock.patch("certbot._internal.main._handle_unexpected_key_type_migration") def test_handle_subset_cert_request(self, mock_handle_migration): @@ -80,8 +80,8 @@ class TestHandleCerts(unittest.TestCase): mock_lineage = mock.Mock() mock_lineage.names.return_value = ["dummy1", "dummy2"] ret = main._handle_subset_cert_request(mock_config, ["dummy1"], mock_lineage) - self.assertEqual(ret, ("renew", mock_lineage)) - self.assertTrue(mock_handle_migration.called) + assert ret == ("renew", mock_lineage) + assert mock_handle_migration.called @mock.patch("certbot._internal.main.display_util.yesno") @mock.patch("certbot._internal.main.cli.set_by_cli") @@ -94,14 +94,14 @@ class TestHandleCerts(unittest.TestCase): cert.private_key_type = "rsa" main._handle_unexpected_key_type_migration(config, cert) mock_yesno.assert_not_called() - self.assertEqual(config.key_type, cert.private_key_type) + assert config.key_type == cert.private_key_type # If the user confirms the change interactively, the key change should proceed silently. cert.private_key_type = "ecdsa" mock_yesno.return_value = True main._handle_unexpected_key_type_migration(config, cert) - self.assertEqual(mock_set.call_count, 2) - self.assertEqual(config.key_type, "rsa") + assert mock_set.call_count == 2 + assert config.key_type == "rsa" # User does not interactively confirm the key type change. mock_yesno.return_value = False @@ -109,24 +109,23 @@ class TestHandleCerts(unittest.TestCase): # If --key-type and --cert-name are both set, the key type change should proceed silently. mock_set.return_value = True main._handle_unexpected_key_type_migration(config, cert) - self.assertEqual(config.key_type, "rsa") + assert config.key_type == "rsa" # If neither --key-type nor --cert-name are set, Certbot should keep the old key type. mock_set.return_value = False main._handle_unexpected_key_type_migration(config, cert) - self.assertEqual(config.key_type, "ecdsa") + assert config.key_type == "ecdsa" # If --key-type is set and --cert-name isn't, Certbot should error. config.key_type = "rsa" mock_set.side_effect = lambda var: var != "certname" - with self.assertRaises(errors.Error) as raised: + with pytest.raises(errors.Error, match="Please provide both --cert-name and --key-type"): main._handle_unexpected_key_type_migration(config, cert) - self.assertIn("Please provide both --cert-name and --key-type", str(raised.exception)) # If --key-type is not set, Certbot should keep the old key type. mock_set.side_effect = lambda var: var != "key_type" main._handle_unexpected_key_type_migration(config, cert) - self.assertEqual(config.key_type, "ecdsa") + assert config.key_type == "ecdsa" class RunTest(test_util.ConfigTestCase): @@ -193,16 +192,16 @@ class RunTest(test_util.ConfigTestCase): mock_choose.return_value = (null.Installer(self.config, "null"), None) plugins = disco.PluginsRegistry.find_all() self.config.auto_hsts = True - self.assertRaises(errors.NotSupportedError, - main.run, - self.config, plugins) + with pytest.raises(errors.NotSupportedError): + main.run(self.config, plugins) @mock.patch('certbot._internal.main._install_cert') def test_cert_success_install_error(self, mock_install_cert): mock_install_cert.side_effect = errors.PluginError("Fake installation error") self.mock_auth.return_value = mock.Mock() self.mock_find_cert.return_value = True, None - self.assertRaises(errors.PluginError, self._call) + with pytest.raises(errors.PluginError): + self._call() # Next steps should contain both renewal advice and installation error self.mock_report_next_steps.assert_called_once_with( @@ -215,9 +214,8 @@ class RunTest(test_util.ConfigTestCase): mock_choose.return_value = (null.Installer(self.config, "null"), None) plugins = disco.PluginsRegistry.find_all() self.config.must_staple = True - self.assertRaises(errors.NotSupportedError, - main.run, - self.config, plugins) + with pytest.raises(errors.NotSupportedError): + main.run(self.config, plugins) class CertonlyTest(unittest.TestCase): """Tests for certbot._internal.main.certonly.""" @@ -252,7 +250,7 @@ class CertonlyTest(unittest.TestCase): self._call('certonly --webroot -d example.com'.split()) def _assert_no_pause(self, *args, **kwargs): # pylint: disable=unused-argument - self.assertIs(kwargs.get("pause"), False) + assert kwargs.get("pause") is False @mock.patch('certbot._internal.main._report_next_steps') @mock.patch('certbot._internal.cert_manager.lineage_for_certname') @@ -268,27 +266,27 @@ class CertonlyTest(unittest.TestCase): self._call(('certonly --webroot -d example.com -d test.org ' '--cert-name example.com').split()) - self.assertEqual(mock_lineage.call_count, 1) - self.assertEqual(mock_domains.call_count, 1) - self.assertEqual(mock_renew_cert.call_count, 1) - self.assertEqual(mock_report_cert.call_count, 1) - self.assertEqual(mock_handle_type.call_count, 1) + assert mock_lineage.call_count == 1 + assert mock_domains.call_count == 1 + assert mock_renew_cert.call_count == 1 + assert mock_report_cert.call_count == 1 + assert mock_handle_type.call_count == 1 mock_report_next_steps.assert_called_once_with( mock.ANY, None, mock.ANY, new_or_renewed_cert=True) # user confirms updating lineage with new domains self._call(('certonly --webroot -d example.com -d test.com ' '--cert-name example.com').split()) - self.assertEqual(mock_lineage.call_count, 2) - self.assertEqual(mock_domains.call_count, 2) - self.assertEqual(mock_renew_cert.call_count, 2) - self.assertEqual(mock_report_cert.call_count, 2) - self.assertEqual(mock_handle_type.call_count, 2) + assert mock_lineage.call_count == 2 + assert mock_domains.call_count == 2 + assert mock_renew_cert.call_count == 2 + assert mock_report_cert.call_count == 2 + assert mock_handle_type.call_count == 2 # error in _ask_user_to_confirm_new_names self.mock_get_utility().yesno.return_value = False - self.assertRaises(errors.ConfigurationError, self._call, - 'certonly --webroot -d example.com -d test.com --cert-name example.com'.split()) + with pytest.raises(errors.ConfigurationError): + self._call('certonly --webroot -d example.com -d test.com --cert-name example.com'.split()) @mock.patch('certbot._internal.main._report_next_steps') @mock.patch('certbot._internal.cert_manager.domains_for_certname') @@ -302,14 +300,14 @@ class CertonlyTest(unittest.TestCase): # no lineage with this name but we specified domains so create a new cert self._call(('certonly --webroot -d example.com -d test.com ' '--cert-name example.com').split()) - self.assertEqual(mock_lineage.call_count, 1) - self.assertEqual(mock_report_cert.call_count, 1) + assert mock_lineage.call_count == 1 + assert mock_report_cert.call_count == 1 # no lineage with this name and we didn't give domains mock_choose_names.return_value = ["somename"] mock_domains_for_certname.return_value = None self._call(('certonly --webroot --cert-name example.com').split()) - self.assertIs(mock_choose_names.called, True) + assert mock_choose_names.called is True @mock.patch('certbot._internal.main._report_next_steps') @mock.patch('certbot._internal.main._get_and_save_cert') @@ -365,24 +363,23 @@ class FindDomainsOrCertnameTest(unittest.TestCase): mock_config = mock.Mock(domains=None, certname=None) mock_choose_names.return_value = "domainname" # pylint: disable=protected-access - self.assertEqual(main._find_domains_or_certname(mock_config, None), ("domainname", None)) + assert main._find_domains_or_certname(mock_config, None) == ("domainname", None) @mock.patch('certbot.display.ops.choose_names') def test_no_results(self, mock_choose_names): mock_config = mock.Mock(domains=None, certname=None) mock_choose_names.return_value = [] # pylint: disable=protected-access - self.assertRaises(errors.Error, main._find_domains_or_certname, mock_config, None) + with pytest.raises(errors.Error): + main._find_domains_or_certname(mock_config, None) @mock.patch('certbot._internal.cert_manager.domains_for_certname') def test_grab_domains(self, mock_domains): mock_config = mock.Mock(domains=None, certname="one.com") mock_domains.return_value = ["one.com", "two.com"] # pylint: disable=protected-access - self.assertEqual( - main._find_domains_or_certname(mock_config, None), + assert main._find_domains_or_certname(mock_config, None) == \ (["one.com", "two.com"], "one.com") - ) class RevokeTest(test_util.TempDirTestCase): @@ -451,7 +448,7 @@ class RevokeTest(test_util.TempDirTestCase): reason.upper()).split() self._call(args) expected.append(mock.call(mock.ANY, code)) - self.assertEqual(expected, mock_revoke.call_args_list) + assert expected == mock_revoke.call_args_list @mock.patch('certbot._internal.main._delete_if_appropriate') @mock.patch('certbot._internal.storage.RenewableCert') @@ -468,8 +465,8 @@ class RevokeTest(test_util.TempDirTestCase): args = 'revoke --cert-name=example.com'.split() mock_delete_if_appropriate.return_value = False self._call(args) - self.assertEqual(mock_acme_from_config.call_args_list[0][0][0].server, - 'https://acme.example') + assert mock_acme_from_config.call_args_list[0][0][0].server == \ + 'https://acme.example' self.mock_success_revoke.assert_called_once_with(self.tmp_cert_path) @mock.patch('certbot._internal.main._delete_if_appropriate') @@ -487,8 +484,8 @@ class RevokeTest(test_util.TempDirTestCase): args = 'revoke --cert-name=example.com --server https://other.example'.split() mock_delete_if_appropriate.return_value = False self._call(args) - self.assertEqual(mock_acme_from_config.call_args_list[0][0][0].server, - 'https://other.example') + assert mock_acme_from_config.call_args_list[0][0][0].server == \ + 'https://other.example' self.mock_success_revoke.assert_called_once_with(self.tmp_cert_path) @mock.patch('certbot._internal.main._delete_if_appropriate') @@ -504,8 +501,8 @@ class RevokeTest(test_util.TempDirTestCase): args = 'revoke --cert-name=example.com'.split() mock_delete_if_appropriate.return_value = False self._call(args) - self.assertEqual(mock_acme_from_config.call_args_list[0][0][0].server, - constants.CLI_DEFAULTS['server']) + assert mock_acme_from_config.call_args_list[0][0][0].server == \ + constants.CLI_DEFAULTS['server'] self.mock_success_revoke.assert_called_once_with(self.tmp_cert_path) @mock.patch('certbot._internal.main._delete_if_appropriate') @@ -517,7 +514,8 @@ class RevokeTest(test_util.TempDirTestCase): def test_revocation_error(self): from acme import errors as acme_errors self.mock_acme_client.side_effect = acme_errors.ClientError() - self.assertRaises(acme_errors.ClientError, self._call) + with pytest.raises(acme_errors.ClientError): + self._call() self.mock_success_revoke.assert_not_called() @mock.patch('certbot._internal.main._delete_if_appropriate') @@ -528,7 +526,7 @@ class RevokeTest(test_util.TempDirTestCase): mock_get_utility().yesno.return_value = False mock_delete_if_appropriate.return_value = False self._call() - self.assertIs(mock_delete.called, False) + assert mock_delete.called is False class ReconfigureTest(test_util.TempDirTestCase): @@ -600,14 +598,14 @@ class ReconfigureTest(test_util.TempDirTestCase): return updated_conf def test_domains_set(self): - self.assertRaises(errors.ConfigurationError, - self._call, '--cert-name cert1 -d one.cert.com'.split()) + with pytest.raises(errors.ConfigurationError): + self._call('--cert-name cert1 -d one.cert.com'.split()) @mock.patch('certbot._internal.cert_manager.get_certnames') def test_asks_for_certname(self, mock_cert_manager): mock_cert_manager.return_value = ['example.com'] self._call('--nginx'.split()) - self.assertEqual(mock_cert_manager.call_count, 1) + assert mock_cert_manager.call_count == 1 def test_update_configurator(self): named_mock = mock.Mock() @@ -618,22 +616,22 @@ class ReconfigureTest(test_util.TempDirTestCase): self.mocks['find_init'].return_value = named_mock new_config = self._call('--cert-name example.com --apache'.split()) - self.assertEqual(new_config['renewalparams']['authenticator'], 'apache') + assert new_config['renewalparams']['authenticator'] == 'apache' @mock.patch('certbot._internal.hooks.validate_hooks') def test_update_hooks(self, unused_validate_hooks): - self.assertNotIn('pre_hook', self.original_config) + assert 'pre_hook' not in self.original_config # test set new_config = self._call('--cert-name example.com --pre-hook'.split() + ['echo pre']) - self.assertEqual(new_config['renewalparams']['pre_hook'], 'echo pre') + assert new_config['renewalparams']['pre_hook'] == 'echo pre' # test update new_config = self._call('--cert-name example.com --pre-hook'.split() + ['echo pre2']) - self.assertEqual(new_config['renewalparams']['pre_hook'], 'echo pre2') + assert new_config['renewalparams']['pre_hook'] == 'echo pre2' # test deploy hook is set even though we did a dry run - self.assertNotIn('renew_hook', self.original_config) + assert 'renew_hook' not in self.original_config new_config = self._call('--cert-name example.com --deploy-hook'.split() + ['echo deploy']) - self.assertEqual(new_config['renewalparams']['renew_hook'], 'echo deploy') + assert new_config['renewalparams']['renew_hook'] == 'echo deploy' def test_dry_run_fails(self): # set side effect of raising error @@ -647,7 +645,7 @@ class ReconfigureTest(test_util.TempDirTestCase): # check that config isn't modified with open(self.renewal_file, 'r') as f: new_config = configobj.ConfigObj(f, encoding='utf-8', default_encoding='utf-8') - self.assertEqual(new_config['renewalparams']['authenticator'], 'nginx') + assert new_config['renewalparams']['authenticator'] == 'nginx' @mock.patch('certbot._internal.main.display_util.notify') def test_report_results(self, mock_notify): @@ -684,7 +682,7 @@ class ReconfigureTest(test_util.TempDirTestCase): self.mocks['find_init'].return_value = named_mock new_config = self._call('--cert-name example.com --nginx'.split()) - self.assertEqual(new_config['renewalparams']['authenticator'], 'nginx') + assert new_config['renewalparams']['authenticator'] == 'nginx' mock_notify.assert_called_with( '\nSuccessfully updated configuration.'+ '\nChanges will apply when the certificate renews.') @@ -732,7 +730,7 @@ class DeleteIfAppropriateTest(test_util.ConfigTestCase): mock_match_and_check_overlaps.side_effect = errors.OverlappingMatchFound() self._call(config) mock_delete.assert_not_called() - self.assertEqual(mock_warning.call_count, 1) + assert mock_warning.call_count == 1 @mock.patch('certbot._internal.storage.renewal_file_for_certname') @mock.patch('certbot._internal.cert_manager.match_and_check_overlaps') @@ -750,7 +748,7 @@ class DeleteIfAppropriateTest(test_util.ConfigTestCase): mock_cert_path_to_lineage.return_value = "example.com" mock_overlapping_archive_dirs.return_value = False self._call(config) - self.assertEqual(mock_delete.call_count, 1) + assert mock_delete.call_count == 1 @mock.patch('certbot._internal.storage.renewal_file_for_certname') @mock.patch('certbot._internal.cert_manager.match_and_check_overlaps') @@ -770,7 +768,7 @@ class DeleteIfAppropriateTest(test_util.ConfigTestCase): mock_full_archive_dir.return_value = "" mock_match_and_check_overlaps.return_value = "" self._call(config) - self.assertEqual(mock_delete.call_count, 1) + assert mock_delete.call_count == 1 @mock.patch('certbot._internal.storage.renewal_file_for_certname') @mock.patch('certbot._internal.cert_manager.match_and_check_overlaps') @@ -789,8 +787,8 @@ class DeleteIfAppropriateTest(test_util.ConfigTestCase): mock_full_archive_dir.return_value = "" mock_match_and_check_overlaps.return_value = "" self._call(config) - self.assertEqual(mock_delete.call_count, 1) - self.assertFalse(mock_get_utility().yesno.called) + assert mock_delete.call_count == 1 + assert not mock_get_utility().yesno.called class DetermineAccountTest(test_util.ConfigTestCase): @@ -824,32 +822,31 @@ class DetermineAccountTest(test_util.ConfigTestCase): try: self._call() except errors.Error as err: - self.assertEqual(f"Unable to register an account with ACME server. {err_msg}", - str(err)) + assert f"Unable to register an account with ACME server. {err_msg}" == \ + str(err) def test_args_account_set(self): self.account_storage.save(self.accs[1], self.mock_client) self.config.account = self.accs[1].id - self.assertEqual((self.accs[1], None), self._call()) - self.assertEqual(self.accs[1].id, self.config.account) - self.assertIsNone(self.config.email) + assert (self.accs[1], None) == self._call() + assert self.accs[1].id == self.config.account + assert self.config.email is None def test_single_account(self): self.account_storage.save(self.accs[0], self.mock_client) - self.assertEqual((self.accs[0], None), self._call()) - self.assertEqual(self.accs[0].id, self.config.account) - self.assertIsNone(self.config.email) + assert (self.accs[0], None) == self._call() + assert self.accs[0].id == self.config.account + assert self.config.email is None @mock.patch('certbot._internal.client.display_ops.choose_account') def test_multiple_accounts(self, mock_choose_accounts): for acc in self.accs: self.account_storage.save(acc, self.mock_client) mock_choose_accounts.return_value = self.accs[1] - self.assertEqual((self.accs[1], None), self._call()) - self.assertEqual( - set(mock_choose_accounts.call_args[0][0]), set(self.accs)) - self.assertEqual(self.accs[1].id, self.config.account) - self.assertIsNone(self.config.email) + assert (self.accs[1], None) == self._call() + assert set(mock_choose_accounts.call_args[0][0]) == set(self.accs) + assert self.accs[1].id == self.config.account + assert self.config.email is None @mock.patch('certbot._internal.client.display_ops.choose_account') def test_multiple_accounts_canceled(self, mock_choose_accounts): @@ -859,7 +856,7 @@ class DetermineAccountTest(test_util.ConfigTestCase): try: self._call() except errors.Error as err: - self.assertIn("No account has been chosen", str(err)) + assert "No account has been chosen" in str(err) @mock.patch('certbot._internal.client.display_ops.get_email') @mock.patch('certbot._internal.main.display_util.notify') @@ -869,12 +866,12 @@ class DetermineAccountTest(test_util.ConfigTestCase): with mock.patch('certbot._internal.main.client') as client: client.register.return_value = ( self.accs[0], mock.sentinel.acme) - self.assertEqual((self.accs[0], mock.sentinel.acme), self._call()) + assert (self.accs[0], mock.sentinel.acme) == self._call() client.register.assert_called_once_with( self.config, self.account_storage, tos_cb=mock.ANY) - self.assertEqual(self.accs[0].id, self.config.account) - self.assertEqual('foo@bar.baz', self.config.email) + assert self.accs[0].id == self.config.account + assert 'foo@bar.baz' == self.config.email mock_notify.assert_called_once_with('Account registered.') def test_no_accounts_email(self): @@ -882,8 +879,8 @@ class DetermineAccountTest(test_util.ConfigTestCase): with mock.patch('certbot._internal.main.client') as client: client.register.return_value = (self.accs[1], mock.sentinel.acme) self._call() - self.assertEqual(self.accs[1].id, self.config.account) - self.assertEqual('other email', self.config.email) + assert self.accs[1].id == self.config.account + assert 'other email' == self.config.email def test_register_error_certbot(self): err_msg = "Some error message raised by Certbot" @@ -959,7 +956,7 @@ class MainTest(test_util.ConfigTestCase): def test_no_flags(self): with mock.patch('certbot._internal.main.run') as mock_run: self._call([]) - self.assertEqual(1, mock_run.call_count) + assert 1 == mock_run.call_count def test_version_string_program_name(self): toy_out = io.StringIO() @@ -972,7 +969,7 @@ class MainTest(test_util.ConfigTestCase): pass finally: output = toy_out.getvalue() or toy_err.getvalue() - self.assertIn("certbot", output, "Output is {0}".format(output)) + assert "certbot" in output, "Output is {0}".format(output) def _cli_missing_flag(self, args, message): "Ensure that a particular error raises a missing cli flag error containing message" @@ -982,8 +979,8 @@ class MainTest(test_util.ConfigTestCase): main.main(self.standard_args + args[:]) # NOTE: parser can alter its args! except errors.MissingCommandlineFlag as exc_: exc = exc_ - self.assertIn(message, str(exc)) - self.assertIsNotNone(exc) + assert message in str(exc) + assert exc is not None @mock.patch('certbot._internal.log.post_arg_parse_setup') def test_noninteractive(self, _): @@ -1011,11 +1008,11 @@ class MainTest(test_util.ConfigTestCase): self._call_no_clientmock(args) os_ver = util.get_os_info_ua() ua = acme_net.call_args[1]["user_agent"] - self.assertIn(os_ver, ua) + assert os_ver in ua import platform plat = platform.platform() if "linux" in plat.lower(): - self.assertIn(util.get_os_info_ua(), ua) + assert util.get_os_info_ua() in ua with mock.patch('certbot._internal.main.client.acme_client') as acme_client: acme_net = acme_client.ClientNetwork @@ -1030,7 +1027,7 @@ class MainTest(test_util.ConfigTestCase): def test_installer_selection(self, mock_pick_installer, _rec): self._call(['install', '--domains', 'foo.bar', '--cert-path', 'cert', '--key-path', 'privkey', '--chain-path', 'chain'], mockisfile=True) - self.assertEqual(mock_pick_installer.call_count, 1) + assert mock_pick_installer.call_count == 1 @mock.patch('certbot._internal.main._install_cert') @mock.patch('certbot._internal.main.plug_sel.record_chosen_plugins') @@ -1045,9 +1042,9 @@ class MainTest(test_util.ConfigTestCase): 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, 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')) + assert call_config.cert_path == test_util.temp_join('cert') + assert call_config.fullchain_path == test_util.temp_join('chain') + assert call_config.key_path == test_util.temp_join('privkey') @mock.patch('certbot._internal.log.post_arg_parse_setup') @mock.patch('certbot._internal.main._install_cert') @@ -1063,26 +1060,25 @@ class MainTest(test_util.ConfigTestCase): self._call(['install', '--cert-name', 'whatever', '--key-path', test_util.temp_join('overriding_privkey')], mockisfile=True) call_config = mock_install.call_args[0][0] - 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')) + assert call_config.cert_path == test_util.temp_join('cert') + assert call_config.fullchain_path == test_util.temp_join('chain') + assert call_config.chain_path == test_util.temp_join('chain') + assert call_config.key_path == test_util.temp_join('overriding_privkey') mock_install.reset() self._call(['install', '--cert-name', 'whatever', '--cert-path', test_util.temp_join('overriding_cert')], mockisfile=True) call_config = mock_install.call_args[0][0] - 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')) + assert call_config.cert_path == test_util.temp_join('overriding_cert') + assert call_config.fullchain_path == test_util.temp_join('chain') + assert call_config.key_path == test_util.temp_join('privkey') @mock.patch('certbot._internal.main.plug_sel.record_chosen_plugins') @mock.patch('certbot._internal.main.plug_sel.pick_installer') def test_installer_param_error(self, _inst, _rec): - self.assertRaises(errors.ConfigurationError, - self._call, - ['install', '--cert-name', 'notfound', + with pytest.raises(errors.ConfigurationError): + self._call(['install', '--cert-name', 'notfound', '--key-path', 'invalid']) @mock.patch('certbot._internal.main.plug_sel.record_chosen_plugins') @@ -1097,8 +1093,8 @@ class MainTest(test_util.ConfigTestCase): with mock.patch("certbot._internal.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) + assert mock_getcert.called + assert mock_inst.called @mock.patch('certbot._internal.eff.handle_subscription') @mock.patch('certbot._internal.log.post_arg_parse_setup') @@ -1125,8 +1121,8 @@ class MainTest(test_util.ConfigTestCase): # Sending nginx a non-existent conf dir will simulate misconfiguration # (we can only do that if certbot-nginx is actually present) ret, _, _, _ = self._call(args) - self.assertIn("The nginx plugin is not working", ret) - self.assertIn("MisconfigurationError", ret) + assert "The nginx plugin is not working" in ret + assert "MisconfigurationError" in ret self._cli_missing_flag(["--standalone"], "With the standalone plugin, you probably") @@ -1135,16 +1131,16 @@ class MainTest(test_util.ConfigTestCase): mock_gsc.return_value = mock.MagicMock() self._call(["certonly", "--manual", "-d", "foo.bar"]) unused_config, auth, unused_installer = mock_init.call_args[0] - self.assertIsInstance(auth, manual.Authenticator) + assert isinstance(auth, manual.Authenticator) with mock.patch('certbot._internal.main.certonly') as mock_certonly: self._call(["auth", "--standalone"]) - self.assertEqual(1, mock_certonly.call_count) + assert 1 == mock_certonly.call_count @mock.patch('certbot._internal.log.post_arg_parse_setup') def test_rollback(self, _): _, _, _, client = self._call(['rollback']) - self.assertEqual(1, client.rollback.call_count) + assert 1 == client.rollback.call_count _, _, _, client = self._call(['rollback', '--checkpoints', '123']) client.rollback.assert_called_once_with( @@ -1153,17 +1149,17 @@ class MainTest(test_util.ConfigTestCase): @mock.patch('certbot._internal.cert_manager.update_live_symlinks') def test_update_symlinks(self, mock_cert_manager): self._call_no_clientmock(['update_symlinks']) - self.assertEqual(1, mock_cert_manager.call_count) + assert 1 == mock_cert_manager.call_count @mock.patch('certbot._internal.cert_manager.certificates') def test_certificates(self, mock_cert_manager): self._call_no_clientmock(['certificates']) - self.assertEqual(1, mock_cert_manager.call_count) + assert 1 == mock_cert_manager.call_count @mock.patch('certbot._internal.cert_manager.delete') def test_delete(self, mock_cert_manager): self._call_no_clientmock(['delete']) - self.assertEqual(1, mock_cert_manager.call_count) + assert 1 == mock_cert_manager.call_count @mock.patch('certbot._internal.main.plugins_disco') @mock.patch('certbot._internal.main.cli.HelpfulArgumentParser.determine_help_topics') @@ -1188,7 +1184,7 @@ class MainTest(test_util.ConfigTestCase): plugins.visible.assert_called_once_with() plugins.visible().ifaces.assert_called_once_with(ifaces) filtered = plugins.visible().ifaces() - self.assertEqual(stdout.getvalue().strip(), str(filtered)) + assert stdout.getvalue().strip() == str(filtered) @mock.patch('certbot._internal.main.plugins_disco') @mock.patch('certbot._internal.main.cli.HelpfulArgumentParser.determine_help_topics') @@ -1210,7 +1206,7 @@ class MainTest(test_util.ConfigTestCase): plugins.visible.assert_called_once_with() plugins.visible().ifaces.assert_called_once_with(ifaces) filtered = plugins.visible().ifaces() - self.assertEqual(stdout.getvalue().strip(), str(filtered)) + assert stdout.getvalue().strip() == str(filtered) @mock.patch('certbot._internal.main.plugins_disco') @mock.patch('certbot._internal.main.cli.HelpfulArgumentParser.determine_help_topics') @@ -1225,8 +1221,8 @@ class MainTest(test_util.ConfigTestCase): plugins.visible.assert_called_once_with() plugins.visible().ifaces.assert_called_once_with(ifaces) filtered = plugins.visible().ifaces() - self.assertEqual(filtered.init.call_count, 1) - self.assertEqual(stdout.getvalue().strip(), str(filtered)) + assert filtered.init.call_count == 1 + assert stdout.getvalue().strip() == str(filtered) @mock.patch('certbot._internal.main.plugins_disco') @mock.patch('certbot._internal.main.cli.HelpfulArgumentParser.determine_help_topics') @@ -1241,11 +1237,11 @@ class MainTest(test_util.ConfigTestCase): plugins.visible.assert_called_once_with() plugins.visible().ifaces.assert_called_once_with(ifaces) filtered = plugins.visible().ifaces() - self.assertEqual(filtered.init.call_count, 1) + assert filtered.init.call_count == 1 filtered.prepare.assert_called_once_with() filtered.available.assert_called_once_with() available = filtered.available() - self.assertEqual(stdout.getvalue().strip(), str(available)) + assert stdout.getvalue().strip() == str(available) def test_certonly_abspath(self): cert = 'cert' @@ -1259,40 +1255,35 @@ class MainTest(test_util.ConfigTestCase): '--fullchain-path', 'fullchain']) config, unused_plugins = mock_certonly.call_args[0] - self.assertEqual(config.cert_path, os.path.abspath(cert)) - self.assertEqual(config.key_path, os.path.abspath(key)) - self.assertEqual(config.chain_path, os.path.abspath(chain)) - self.assertEqual(config.fullchain_path, os.path.abspath(fullchain)) + assert config.cert_path == os.path.abspath(cert) + assert config.key_path == os.path.abspath(key) + assert config.chain_path == os.path.abspath(chain) + assert config.fullchain_path == os.path.abspath(fullchain) def test_certonly_bad_args(self): try: self._call(['-a', 'bad_auth', 'certonly']) assert False, "Exception should have been raised" except errors.PluginSelectionError as e: - self.assertIn('The requested bad_auth plugin does not appear', str(e)) + assert 'The requested bad_auth plugin does not appear' in str(e) def test_check_config_sanity_domain(self): # FQDN - self.assertRaises(errors.ConfigurationError, - self._call, - ['-d', 'a' * 64]) + with pytest.raises(errors.ConfigurationError): + self._call(['-d', 'a' * 64]) # FQDN 2 - self.assertRaises(errors.ConfigurationError, - self._call, - ['-d', (('a' * 50) + '.') * 10]) + with pytest.raises(errors.ConfigurationError): + self._call(['-d', (('a' * 50) + '.') * 10]) # Bare IP address (this is actually a different error message now) - self.assertRaises(errors.ConfigurationError, - self._call, - ['-d', '204.11.231.35']) + with pytest.raises(errors.ConfigurationError): + self._call(['-d', '204.11.231.35']) # Bare IPv6 address - self.assertRaises(errors.ConfigurationError, - self._call, - ['-d', '2001:db8:ac69:3ff:b1cb:c8c6:5a84:a31b']) + with pytest.raises(errors.ConfigurationError): + self._call(['-d', '2001:db8:ac69:3ff:b1cb:c8c6:5a84:a31b']) def test_csr_with_besteffort(self): - self.assertRaises( - errors.Error, self._call, - 'certonly --csr {0} --allow-subset-of-names'.format(CSR).split()) + with pytest.raises(errors.Error): + self._call('certonly --csr {0} --allow-subset-of-names'.format(CSR).split()) def test_run_with_csr(self): # This is an error because you can only use --csr with certonly @@ -1304,15 +1295,13 @@ class MainTest(test_util.ConfigTestCase): assert False, "Expected supplying --csr to fail with default verb" def test_csr_with_no_domains(self): - self.assertRaises( - errors.Error, self._call, - 'certonly --csr {0}'.format( + with pytest.raises(errors.Error): + self._call('certonly --csr {0}'.format( test_util.vector_path('csr-nonames_512.pem')).split()) def test_csr_with_inconsistent_domains(self): - self.assertRaises( - errors.Error, self._call, - 'certonly -d example.org --csr {0}'.format(CSR).split()) + with pytest.raises(errors.Error): + self._call('certonly -d example.org --csr {0}'.format(CSR).split()) def _certonly_new_request_common(self, mock_client, args=None): with mock.patch('certbot._internal.main._find_lineage_for_domains_and_certname') \ @@ -1330,10 +1319,9 @@ class MainTest(test_util.ConfigTestCase): mock_client = mock.MagicMock() mock_client.obtain_and_enroll_certificate.return_value = None self._certonly_new_request_common(mock_client, ['--dry-run']) - self.assertEqual( - mock_client.obtain_and_enroll_certificate.call_count, 1) - self.assertEqual(mock_report.call_count, 1) - self.assertIs(mock_report.call_args[0][0].dry_run, True) + assert mock_client.obtain_and_enroll_certificate.call_count == 1 + assert mock_report.call_count == 1 + assert mock_report.call_args[0][0].dry_run is True @mock.patch('certbot._internal.main._report_new_cert') @mock.patch('certbot._internal.main.util.atexit_register') @@ -1351,21 +1339,20 @@ class MainTest(test_util.ConfigTestCase): mock_client = mock.MagicMock() mock_client.obtain_and_enroll_certificate.return_value = mock_lineage self._certonly_new_request_common(mock_client) - self.assertEqual( - mock_client.obtain_and_enroll_certificate.call_count, 1) - self.assertEqual(mock_report.call_count, 1) - self.assertIn(cert_path, mock_report.call_args[0][2]) - self.assertIn(key_path, mock_report.call_args[0][3]) - self.assertIn('donate', mock_register.call_args[0][1]) - self.assertIs(mock_subscription.called, True) + assert mock_client.obtain_and_enroll_certificate.call_count == 1 + assert mock_report.call_count == 1 + assert cert_path in mock_report.call_args[0][2] + assert key_path in mock_report.call_args[0][3] + assert 'donate' in mock_register.call_args[0][1] + assert mock_subscription.called is True @mock.patch('certbot._internal.eff.handle_subscription') def test_certonly_new_request_failure(self, mock_subscription): mock_client = mock.MagicMock() mock_client.obtain_and_enroll_certificate.return_value = False - self.assertRaises(errors.Error, - self._certonly_new_request_common, mock_client) - self.assertIs(mock_subscription.called, False) + with pytest.raises(errors.Error): + self._certonly_new_request_common(mock_client) + assert mock_subscription.called is False def _test_renewal_common(self, due_for_renewal, extra_args, log_out=None, args=None, should_renew=True, error_expected=False, @@ -1431,14 +1418,14 @@ class MainTest(test_util.ConfigTestCase): else: mock_client.obtain_certificate.assert_called_once_with([mock.ANY], None) else: - self.assertEqual(mock_client.obtain_certificate.call_count, 0) + assert mock_client.obtain_certificate.call_count == 0 except: self._dump_log() raise finally: if log_out: with open(os.path.join(self.config.logs_dir, "letsencrypt.log")) as lf: - self.assertIn(log_out, lf.read()) + assert log_out in lf.read() return mock_lineage, mock_display, stdout @@ -1447,12 +1434,12 @@ class MainTest(test_util.ConfigTestCase): @mock.patch('certbot.crypto_util.notAfter') def test_certonly_renewal(self, _, mock_register, mock_report): lineage, _, _ = self._test_renewal_common(True, []) - self.assertEqual(lineage.save_successor.call_count, 1) + assert lineage.save_successor.call_count == 1 lineage.update_all_links_to.assert_called_once_with( lineage.latest_common_version()) - self.assertEqual(mock_report.call_count, 1) - self.assertIn('fullchain.pem', mock_report.call_args[0][2]) - self.assertIn('donate', mock_register.call_args[0][1]) + assert mock_report.call_count == 1 + assert 'fullchain.pem' in mock_report.call_args[0][2] + assert 'donate' in mock_register.call_args[0][1] @mock.patch('certbot._internal.main.display_util.notify') @mock.patch('certbot._internal.log.logging.handlers.RotatingFileHandler.doRollover') @@ -1468,7 +1455,7 @@ class MainTest(test_util.ConfigTestCase): _, mock_displayer, _ = self._test_renewal_common(False, ['-tvv', '--debug', '--keep'], should_renew=False) - self.assertIn('not yet due', mock_displayer().notification.call_args[0][0]) + assert 'not yet due' in mock_displayer().notification.call_args[0][0] def _dump_log(self): print("Logs:") @@ -1506,11 +1493,11 @@ class MainTest(test_util.ConfigTestCase): test_util.make_lineage(self.config.config_dir, 'sample-renewal.conf') args = ["renew", "--dry-run", "-tvv"] self._test_renewal_common(True, [], args=args, should_renew=True) - self.assertEqual(self.mock_sleep.call_count, 1) + assert self.mock_sleep.call_count == 1 # in main.py: # sleep_time = random.randint(1, 60*8) sleep_call_arg = self.mock_sleep.call_args[0][0] - self.assertTrue(1 <= sleep_call_arg <= 60*8) + assert 1 <= sleep_call_arg <= 60*8 @mock.patch('sys.stdin') def test_interactive_no_renewal_delay(self, stdin): @@ -1518,7 +1505,7 @@ class MainTest(test_util.ConfigTestCase): test_util.make_lineage(self.config.config_dir, 'sample-renewal.conf') args = ["renew", "--dry-run", "-tvv"] self._test_renewal_common(True, [], args=args, should_renew=True) - self.assertEqual(self.mock_sleep.call_count, 0) + assert self.mock_sleep.call_count == 0 @mock.patch('certbot._internal.renewal.should_renew') def test_renew_skips_recent_certs(self, should_renew): @@ -1527,8 +1514,8 @@ class MainTest(test_util.ConfigTestCase): expiry = datetime.datetime.now() + datetime.timedelta(days=90) _, _, stdout = self._test_renewal_common(False, extra_args=None, should_renew=False, args=['renew'], expiry_date=expiry) - self.assertIn('No renewals were attempted.', stdout.getvalue()) - self.assertIn('The following certificates are not due for renewal yet:', stdout.getvalue()) + assert 'No renewals were attempted.' in stdout.getvalue() + assert 'The following certificates are not due for renewal yet:' in stdout.getvalue() @mock.patch('certbot._internal.log.post_arg_parse_setup') def test_quiet_renew(self, _): @@ -1536,13 +1523,13 @@ class MainTest(test_util.ConfigTestCase): args = ["renew", "--dry-run"] _, _, stdout = self._test_renewal_common(True, [], args=args, should_renew=True) out = stdout.getvalue() - self.assertIn("renew", out) + assert "renew" in out args = ["renew", "--dry-run", "-q"] _, _, stdout = self._test_renewal_common(True, [], args=args, should_renew=True, quiet_mode=True) out = stdout.getvalue() - self.assertEqual("", out) + assert "" == out def test_renew_hook_validation(self): test_util.make_lineage(self.config.config_dir, 'sample-renewal.conf') @@ -1600,9 +1587,9 @@ class MainTest(test_util.ConfigTestCase): if assert_oc_called is not None: if assert_oc_called: - self.assertTrue(mock_renew_cert.called) + assert mock_renew_cert.called else: - self.assertIs(mock_renew_cert.called, False) + assert mock_renew_cert.called is False def test_renew_no_renewalparams(self): self._test_renew_common(assert_oc_called=False, error_expected=True) @@ -1681,7 +1668,7 @@ class MainTest(test_util.ConfigTestCase): args=['renew', '--post-hook', '{0} -c "print(\'hello world\');"' .format(sys.executable)]) - self.assertIn('No hooks were run.', stdout.getvalue()) + assert 'No hooks were run.' in stdout.getvalue() @test_util.patch_display_util() @mock.patch('certbot._internal.main._find_lineage_for_domains_and_certname') @@ -1692,9 +1679,9 @@ class MainTest(test_util.ConfigTestCase): mock_renewal.return_value = ('reinstall', mock.MagicMock()) mock_init.return_value = mock_client = mock.MagicMock() self._call(['-d', 'foo.bar', '-a', 'standalone', 'certonly']) - self.assertIs(mock_client.obtain_certificate.called, False) - self.assertIs(mock_client.obtain_and_enroll_certificate.called, False) - self.assertEqual(mock_get_utility().add_message.call_count, 0) + assert mock_client.obtain_certificate.called is False + assert mock_client.obtain_and_enroll_certificate.called is False + assert mock_get_utility().add_message.call_count == 0 mock_report_new_cert.assert_not_called() #self.assertTrue('donate' not in mock_get_utility().add_message.call_args[0][0]) @@ -1724,7 +1711,7 @@ class MainTest(test_util.ConfigTestCase): self._call(args) if '--dry-run' in args: - self.assertIs(mock_client.save_certificate.called, False) + assert mock_client.save_certificate.called is False else: mock_client.save_certificate.assert_called_once_with( certr, chain, cert_path, chain_path, full_path) @@ -1734,18 +1721,18 @@ class MainTest(test_util.ConfigTestCase): @mock.patch('certbot._internal.eff.handle_subscription') def test_certonly_csr(self, mock_subscription, mock_register, mock_csr_report): self._test_certonly_csr_common() - self.assertEqual(mock_csr_report.call_count, 1) - self.assertIn('cert_512.pem', mock_csr_report.call_args[0][1]) - self.assertIsNone(mock_csr_report.call_args[0][2]) - self.assertIn('fullchain.pem', mock_csr_report.call_args[0][3]) - self.assertIn('donate', mock_register.call_args[0][1]) - self.assertIs(mock_subscription.called, True) + assert mock_csr_report.call_count == 1 + assert 'cert_512.pem' in mock_csr_report.call_args[0][1] + assert mock_csr_report.call_args[0][2] is None + assert 'fullchain.pem' in mock_csr_report.call_args[0][3] + assert 'donate' in mock_register.call_args[0][1] + assert mock_subscription.called is True @mock.patch('certbot._internal.main._csr_report_new_cert') def test_certonly_csr_dry_run(self, mock_csr_report): self._test_certonly_csr_common(['--dry-run']) - self.assertEqual(mock_csr_report.call_count, 1) - self.assertIs(mock_csr_report.call_args[0][0].dry_run, True) + assert mock_csr_report.call_count == 1 + assert mock_csr_report.call_args[0][0].dry_run is True @mock.patch('certbot._internal.main._delete_if_appropriate') @mock.patch('certbot._internal.main.client.acme_client') @@ -1756,9 +1743,9 @@ class MainTest(test_util.ConfigTestCase): self._call_no_clientmock(['--cert-path', SS_CERT_PATH, '--key-path', RSA2048_KEY_PATH, '--server', server, 'revoke']) with open(RSA2048_KEY_PATH, 'rb') as f: - self.assertEqual(mock_acme_client.ClientV2.call_count, 1) - self.assertEqual(mock_acme_client.ClientNetwork.call_args[0][0], - jose.JWK.load(f.read())) + assert mock_acme_client.ClientV2.call_count == 1 + assert mock_acme_client.ClientNetwork.call_args[0][0] == \ + jose.JWK.load(f.read()) with open(SS_CERT_PATH, 'rb') as f: cert = crypto_util.pyopenssl_load_certificate(f.read())[0] mock_revoke = mock_acme_client.ClientV2().revoke @@ -1768,8 +1755,8 @@ class MainTest(test_util.ConfigTestCase): def test_revoke_with_key_mismatch(self): server = 'foo.bar' - self.assertRaises(errors.Error, self._call_no_clientmock, - ['--cert-path', CERT, '--key-path', KEY, + with pytest.raises(errors.Error): + self._call_no_clientmock(['--cert-path', CERT, '--key-path', KEY, '--server', server, 'revoke']) @mock.patch('certbot._internal.main._delete_if_appropriate') @@ -1801,20 +1788,20 @@ class MainTest(test_util.ConfigTestCase): mocked_account.AccountFileStorage.return_value = mocked_storage mocked_storage.find_all.return_value = ["an account"] x = self._call_no_clientmock(["register", "--email", "user@example.org"]) - self.assertIn("There is an existing account", x[0]) + assert "There is an existing account" in x[0] @mock.patch('certbot._internal.plugins.selection.choose_configurator_plugins') @mock.patch('certbot._internal.updater._run_updaters') def test_plugin_selection_error(self, mock_run, mock_choose): mock_choose.side_effect = errors.PluginSelectionError - self.assertRaises(errors.PluginSelectionError, main.renew_cert, - None, None, None) + with pytest.raises(errors.PluginSelectionError): + main.renew_cert(None, None, None) self.config.dry_run = False updater.run_generic_updaters(self.config, None, None) # Make sure we're returning None, and hence not trying to run the # without installer - self.assertIs(mock_run.called, False) + assert mock_run.called is False @mock.patch('certbot._internal.main.updater.run_renewal_deployer') @mock.patch('certbot._internal.plugins.selection.choose_configurator_plugins') @@ -1829,8 +1816,8 @@ class MainTest(test_util.ConfigTestCase): main.renew_cert(self.config, None, None) - self.assertEqual(mock_init.call_count, 1) - self.assertEqual(mock_get_cert.call_count, 1) + assert mock_init.call_count == 1 + assert mock_get_cert.call_count == 1 installer.restart.assert_not_called() mock_run_renewal_deployer.assert_not_called() @@ -1858,7 +1845,7 @@ class UnregisterTest(unittest.TestCase): unused_plugins = mock.Mock() res = main.unregister(config, unused_plugins) - self.assertEqual(res, "Deactivation aborted.") + assert res == "Deactivation aborted." @mock.patch("certbot._internal.main.display_util.notify") def test_unregister(self, mock_notify): @@ -1876,7 +1863,7 @@ class UnregisterTest(unittest.TestCase): res = main.unregister(config, unused_plugins) - self.assertIsNone(res) + assert res is None mock_notify.assert_called_once_with("Account deactivated.") def test_unregister_no_account(self): @@ -1893,8 +1880,8 @@ class UnregisterTest(unittest.TestCase): res = main.unregister(config, unused_plugins) m = "Could not find existing account for server https://acme.example.com/directory." - self.assertEqual(res, m) - self.assertIs(cb_client.acme.deactivate_registration.called, False) + assert res == m + assert cb_client.acme.deactivate_registration.called is False class MakeOrVerifyNeededDirs(test_util.ConfigTestCase): @@ -1956,9 +1943,9 @@ class EnhanceTest(test_util.ConfigTestCase): mock_find.return_value = (None, None) with mock.patch('certbot._internal.main.plug_sel.pick_installer') as mock_pick: self._call(['enhance', '--redirect']) - self.assertTrue(mock_pick.called) + assert mock_pick.called # Check that the message includes "enhancements" - self.assertIn("enhancements", mock_pick.call_args[0][3]) + assert "enhancements" in mock_pick.call_args[0][3] @mock.patch('certbot._internal.main.plug_sel.record_chosen_plugins') @mock.patch('certbot._internal.cert_manager.lineage_for_certname') @@ -1971,9 +1958,9 @@ class EnhanceTest(test_util.ConfigTestCase): with mock.patch('certbot._internal.main.plug_sel.pick_installer'): with mock.patch('certbot._internal.main.plug_sel.logger.warning') as mock_log: mock_client = self._call(['enhance', '-a', 'webroot', '--redirect']) - self.assertTrue(mock_log.called) - self.assertIn("make sense", mock_log.call_args[0][0]) - self.assertTrue(mock_client.enhance_config.called) + assert mock_log.called + assert "make sense" in mock_log.call_args[0][0] + assert mock_client.enhance_config.called @mock.patch('certbot._internal.cert_manager.lineage_for_certname') @mock.patch('certbot._internal.main.display_ops.choose_values') @@ -1985,13 +1972,10 @@ class EnhanceTest(test_util.ConfigTestCase): mock_client = self._call(['enhance', '--redirect', '--hsts']) req_enh = ["redirect", "hsts"] not_req_enh = ["uir"] - self.assertTrue(mock_client.enhance_config.called) - self.assertTrue( - all(getattr(mock_client.config, e) for e in req_enh)) - self.assertFalse( - any(getattr(mock_client.config, e) for e in not_req_enh)) - self.assertIn( - "example.com", mock_client.enhance_config.call_args[0][0]) + assert mock_client.enhance_config.called + assert all(getattr(mock_client.config, e) for e in req_enh) + assert not any(getattr(mock_client.config, e) for e in not_req_enh) + assert "example.com" in mock_client.enhance_config.call_args[0][0] @mock.patch('certbot._internal.cert_manager.lineage_for_certname') @mock.patch('certbot._internal.main.display_ops.choose_values') @@ -2003,21 +1987,20 @@ class EnhanceTest(test_util.ConfigTestCase): with mock.patch('certbot._internal.main.plug_sel.pick_installer'): mock_client = self._call(['enhance', '--redirect', '--hsts', '--non-interactive']) - self.assertTrue(mock_client.enhance_config.called) - self.assertIs(mock_choose.called, False) + assert mock_client.enhance_config.called + assert mock_choose.called is False @mock.patch('certbot._internal.main.display_ops.choose_values') @mock.patch('certbot._internal.main.plug_sel.record_chosen_plugins') def test_user_abort_domains(self, _rec, mock_choose): mock_choose.return_value = [] with mock.patch('certbot._internal.main.plug_sel.pick_installer'): - self.assertRaises(errors.Error, - self._call, - ['enhance', '--redirect', '--hsts']) + with pytest.raises(errors.Error): + self._call(['enhance', '--redirect', '--hsts']) def test_no_enhancements_defined(self): - self.assertRaises(errors.MisconfigurationError, - self._call, ['enhance', '-a', 'null']) + with pytest.raises(errors.MisconfigurationError): + self._call(['enhance', '-a', 'null']) @mock.patch('certbot._internal.main.plug_sel.choose_configurator_plugins') @mock.patch('certbot._internal.main.display_ops.choose_values') @@ -2027,7 +2010,7 @@ class EnhanceTest(test_util.ConfigTestCase): mock_pick.return_value = (None, None) mock_pick.side_effect = errors.PluginSelectionError() mock_client = self._call(['enhance', '--hsts']) - self.assertIs(mock_client.enhance_config.called, False) + assert mock_client.enhance_config.called is False @mock.patch('certbot._internal.cert_manager.lineage_for_certname') @mock.patch('certbot._internal.main.display_ops.choose_values') @@ -2039,9 +2022,9 @@ class EnhanceTest(test_util.ConfigTestCase): mock_choose.return_value = ["example.com", "another.tld"] mock_lineage.return_value = mock.MagicMock(chain_path="/tmp/nonexistent") self._call(['enhance', '--auto-hsts']) - self.assertTrue(self.mockinstaller.enable_autohsts.called) - self.assertEqual(self.mockinstaller.enable_autohsts.call_args[0][1], - ["example.com", "another.tld"]) + assert self.mockinstaller.enable_autohsts.called + assert self.mockinstaller.enable_autohsts.call_args[0][1] == \ + ["example.com", "another.tld"] @mock.patch('certbot._internal.cert_manager.lineage_for_certname') @mock.patch('certbot._internal.main.display_ops.choose_values') @@ -2052,14 +2035,12 @@ class EnhanceTest(test_util.ConfigTestCase): mock_inst.return_value = null.Installer(self.config, "null") mock_choose.return_value = ["example.com", "another.tld"] mock_lineage.return_value = mock.MagicMock(chain_path="/tmp/nonexistent") - self.assertRaises( - errors.NotSupportedError, - self._call, ['enhance', '--auto-hsts']) + with pytest.raises(errors.NotSupportedError): + self._call(['enhance', '--auto-hsts']) def test_enhancement_enable_conflict(self): - self.assertRaises( - errors.Error, - self._call, ['enhance', '--auto-hsts', '--hsts']) + with pytest.raises(errors.Error): + self._call(['enhance', '--auto-hsts', '--hsts']) class InstallTest(test_util.ConfigTestCase): @@ -2076,9 +2057,8 @@ class InstallTest(test_util.ConfigTestCase): plugins = disco.PluginsRegistry.find_all() self.config.auto_hsts = True self.config.certname = "nonexistent" - self.assertRaises(errors.NotSupportedError, - main.install, - self.config, plugins) + with pytest.raises(errors.NotSupportedError): + main.install(self.config, plugins) @mock.patch('certbot._internal.main.plug_sel.record_chosen_plugins') @mock.patch('certbot._internal.main.plug_sel.pick_installer') @@ -2089,9 +2069,8 @@ class InstallTest(test_util.ConfigTestCase): self.config.certname = None self.config.key_path = "/tmp/nonexistent" self.config.cert_path = "/tmp/nonexistent" - self.assertRaises(errors.ConfigurationError, - main.install, - self.config, plugins) + with pytest.raises(errors.ConfigurationError): + main.install(self.config, plugins) class ReportNewCertTest(unittest.TestCase): @@ -2131,10 +2110,10 @@ class ReportNewCertTest(unittest.TestCase): self.mock_notify.assert_called_with("The dry run was successful.") def test_report_no_paths(self): - with self.assertRaises(AssertionError): + with pytest.raises(AssertionError): self._call(mock.Mock(dry_run=False), None, None, None) - with self.assertRaises(AssertionError): + with pytest.raises(AssertionError): self._call_csr(mock.Mock(dry_run=False), None, None, None) def test_report(self): @@ -2228,8 +2207,8 @@ class ReportNextStepsTest(unittest.TestCase): _report_next_steps(*args, **kwargs) def _output(self) -> str: - self.assertEqual(self.mock_notify.call_count, 2) - self.assertEqual(self.mock_notify.call_args_list[0][0][0], 'NEXT STEPS:') + assert self.mock_notify.call_count == 2 + assert self.mock_notify.call_args_list[0][0][0] == 'NEXT STEPS:' return self.mock_notify.call_args_list[1][0][0] def test_report(self): @@ -2243,19 +2222,19 @@ class ReportNextStepsTest(unittest.TestCase): """--csr requires manual renewal""" self.config.csr = "foo.csr" self._call(self.config, None, None) - self.assertIn("--csr will not be renewed", self._output()) + assert "--csr will not be renewed" in self._output() def test_manual_no_hook_renewal(self): """--manual without a hook requires manual renewal""" self.config.authenticator = "manual" self._call(self.config, None, None) - self.assertIn("--manual certificates requires", self._output()) + assert "--manual certificates requires" in self._output() def test_no_preconfigured_renewal(self): """No --preconfigured-renewal needs manual cron setup""" self.config.preconfigured_renewal = False self._call(self.config, None, None) - self.assertIn("https://certbot.org/renewal-setup", self._output()) + assert "https://certbot.org/renewal-setup" in self._output() class UpdateAccountTest(test_util.ConfigTestCase): @@ -2300,12 +2279,12 @@ class UpdateAccountTest(test_util.ConfigTestCase): (_, mock_storage, mock_regr) = self._prepare_mock_account() result = self._call(args) # When update succeeds, the return value of update_account() is None - self.assertIsNone(result) + assert result is None # We submitted a registration to the server - self.assertEqual(self.mocks['client'].Client().acme.update_registration.call_count, 1) + assert self.mocks['client'].Client().acme.update_registration.call_count == 1 mock_regr.body.update.assert_called_with(contact=()) # We got an update from the server and persisted it - self.assertEqual(mock_storage.update_regr.call_count, 1) + assert mock_storage.update_regr.call_count == 1 # We should have notified the user self.mocks['notify'].assert_called_with( 'Any contact information associated with this account has been removed.' @@ -2318,9 +2297,9 @@ class UpdateAccountTest(test_util.ConfigTestCase): mock_storage = mock.MagicMock() mock_storage.find_all.return_value = [] self.mocks['account'].AccountFileStorage.return_value = mock_storage - self.assertEqual(self._call(['update_account', '--email', 'user@example.org']), - 'Could not find an existing account for server' - ' https://acme-v02.api.letsencrypt.org/directory.') + assert self._call(['update_account', '--email', 'user@example.org']) == \ + 'Could not find an existing account for server' \ + ' https://acme-v02.api.letsencrypt.org/directory.' def test_update_account_remove_email(self): """Test that --register-unsafely-without-email is handled as no email""" @@ -2340,13 +2319,13 @@ class UpdateAccountTest(test_util.ConfigTestCase): result = self._call(['update_account']) # None if registration succeeds - self.assertIsNone(result) + assert result is None # We should have updated the server - self.assertEqual(mock_client.acme.update_registration.call_count, 1) + assert mock_client.acme.update_registration.call_count == 1 # We should have updated the account on disk - self.assertEqual(mock_storage.update_regr.call_count, 1) + assert mock_storage.update_regr.call_count == 1 # Subscription should have been prompted - self.assertEqual(self.mocks['prepare_sub'].call_count, 1) + assert self.mocks['prepare_sub'].call_count == 1 # Should have printed the email self.mocks['notify'].assert_called_with( 'Your e-mail address was updated to user@example.com.') @@ -2354,13 +2333,11 @@ class UpdateAccountTest(test_util.ConfigTestCase): def test_update_account_with_multiple_emails(self): """Test that multiple email addresses are handled correctly""" (_, mock_storage, mock_regr) = self._prepare_mock_account() - self.assertIsNone( - self._call(['update_account', '-m', 'user@example.com,user@example.org']) - ) + assert self._call(['update_account', '-m', 'user@example.com,user@example.org']) is None mock_regr.body.update.assert_called_with( contact=['mailto:user@example.com', 'mailto:user@example.org'] ) - self.assertEqual(mock_storage.update_regr.call_count, 1) + assert mock_storage.update_regr.call_count == 1 self.mocks['notify'].assert_called_with( 'Your e-mail address was updated to user@example.com,user@example.org.') @@ -2414,16 +2391,16 @@ class ShowAccountTest(test_util.ConfigTestCase): self._call(args) - self.assertEqual(mock_client.acme.query_registration.call_count, 1) + assert mock_client.acme.query_registration.call_count == 1 def test_no_existing_accounts(self): """Test that no existing account is handled correctly""" mock_storage = mock.MagicMock() mock_storage.find_all.return_value = [] self.mocks['account'].AccountFileStorage.return_value = mock_storage - self.assertEqual(self._call(['show_account']), - 'Could not find an existing account for server' - ' https://acme-v02.api.letsencrypt.org/directory.') + assert self._call(['show_account']) == \ + 'Could not find an existing account for server' \ + ' https://acme-v02.api.letsencrypt.org/directory.' def test_no_existing_client(self): """Test that issues with the ACME client are handled correctly""" @@ -2434,12 +2411,12 @@ class ShowAccountTest(test_util.ConfigTestCase): try: self._call(['show_account']) except errors.Error as e: - self.assertEqual('ACME client is not set.', str(e)) + assert 'ACME client is not set.' == str(e) def test_no_contacts(self): self._test_show_account(()) - self.assertEqual(self.mocks['notify'].call_count, 1) + assert self.mocks['notify'].call_count == 1 self.mocks['notify'].assert_has_calls([ mock.call('Account details for server https://acme-v02.api.letsencr' 'ypt.org/directory:\n Account URL: https://www.letsencry' @@ -2450,7 +2427,7 @@ class ShowAccountTest(test_util.ConfigTestCase): contact = ('mailto:foo@example.com',) self._test_show_account(contact) - self.assertEqual(self.mocks['notify'].call_count, 1) + assert self.mocks['notify'].call_count == 1 self.mocks['notify'].assert_has_calls([ mock.call('Account details for server https://acme-v02.api.letsencr' 'ypt.org/directory:\n Account URL: https://www.letsencry' @@ -2461,7 +2438,7 @@ class ShowAccountTest(test_util.ConfigTestCase): contact = ('mailto:foo@example.com', 'mailto:bar@example.com') self._test_show_account(contact) - self.assertEqual(self.mocks['notify'].call_count, 1) + assert self.mocks['notify'].call_count == 1 self.mocks['notify'].assert_has_calls([ mock.call('Account details for server https://acme-v02.api.letsencr' 'ypt.org/directory:\n Account URL: https://www.letsencry' diff --git a/certbot/tests/ocsp_test.py b/certbot/tests/ocsp_test.py index 4f7a39956..8dfeaf9a9 100644 --- a/certbot/tests/ocsp_test.py +++ b/certbot/tests/ocsp_test.py @@ -49,20 +49,20 @@ class OCSPTestOpenSSL(unittest.TestCase): from certbot import ocsp checker = ocsp.RevocationChecker(enforce_openssl_binary_usage=True) - self.assertEqual(mock_run.call_count, 1) - self.assertEqual(checker.host_args("x"), ["Host=x"]) + assert mock_run.call_count == 1 + assert checker.host_args("x") == ["Host=x"] mock_run.return_value.stderr = out.partition("\n")[2] checker = ocsp.RevocationChecker(enforce_openssl_binary_usage=True) - self.assertEqual(checker.host_args("x"), ["Host", "x"]) - self.assertIs(checker.broken, False) + assert checker.host_args("x") == ["Host", "x"] + assert checker.broken is False mock_exists.return_value = False mock_run.call_count = 0 checker = ocsp.RevocationChecker(enforce_openssl_binary_usage=True) - self.assertEqual(mock_run.call_count, 0) - self.assertEqual(mock_log.call_count, 1) - self.assertIs(checker.broken, True) + assert mock_run.call_count == 0 + assert mock_log.call_count == 1 + assert checker.broken is True @mock.patch('certbot.ocsp._determine_ocsp_server') @mock.patch('certbot.ocsp.crypto_util.notAfter') @@ -76,32 +76,32 @@ class OCSPTestOpenSSL(unittest.TestCase): self.checker.broken = True mock_determine.return_value = ("", "") - self.assertIs(self.checker.ocsp_revoked(cert_obj), False) + assert self.checker.ocsp_revoked(cert_obj) is False self.checker.broken = False mock_run.return_value = tuple(openssl_happy[1:]) - self.assertIs(self.checker.ocsp_revoked(cert_obj), False) - self.assertEqual(mock_run.call_count, 0) + assert self.checker.ocsp_revoked(cert_obj) is False + assert mock_run.call_count == 0 mock_determine.return_value = ("http://x.co", "x.co") - self.assertIs(self.checker.ocsp_revoked(cert_obj), False) + assert self.checker.ocsp_revoked(cert_obj) is False mock_run.side_effect = errors.SubprocessError("Unable to load certificate launcher") - self.assertIs(self.checker.ocsp_revoked(cert_obj), False) - self.assertEqual(mock_run.call_count, 2) + assert self.checker.ocsp_revoked(cert_obj) is False + assert mock_run.call_count == 2 # cert expired mock_na.return_value = now mock_determine.return_value = ("", "") count_before = mock_determine.call_count - self.assertIs(self.checker.ocsp_revoked(cert_obj), False) - self.assertEqual(mock_determine.call_count, count_before) + assert self.checker.ocsp_revoked(cert_obj) is False + assert mock_determine.call_count == count_before def test_determine_ocsp_server(self): cert_path = test_util.vector_path('ocsp_certificate.pem') from certbot import ocsp result = ocsp._determine_ocsp_server(cert_path) - self.assertEqual(('http://ocsp.test4.buypass.com', 'ocsp.test4.buypass.com'), result) + assert ('http://ocsp.test4.buypass.com', 'ocsp.test4.buypass.com') == result @mock.patch('certbot.ocsp.logger') @mock.patch('certbot.util.run_script') @@ -109,23 +109,23 @@ class OCSPTestOpenSSL(unittest.TestCase): # pylint: disable=protected-access mock_run.return_value = openssl_confused from certbot import ocsp - self.assertIs(ocsp._translate_ocsp_query(*openssl_happy), False) - self.assertIs(ocsp._translate_ocsp_query(*openssl_confused), False) - self.assertEqual(mock_log.debug.call_count, 1) - self.assertEqual(mock_log.warning.call_count, 0) + assert ocsp._translate_ocsp_query(*openssl_happy) is False + assert ocsp._translate_ocsp_query(*openssl_confused) is False + assert mock_log.debug.call_count == 1 + assert mock_log.warning.call_count == 0 mock_log.debug.call_count = 0 - self.assertIs(ocsp._translate_ocsp_query(*openssl_unknown), False) - self.assertEqual(mock_log.debug.call_count, 1) - self.assertEqual(mock_log.warning.call_count, 0) - self.assertIs(ocsp._translate_ocsp_query(*openssl_expired_ocsp), False) - self.assertEqual(mock_log.debug.call_count, 2) - self.assertIs(ocsp._translate_ocsp_query(*openssl_broken), False) - self.assertEqual(mock_log.warning.call_count, 1) + assert ocsp._translate_ocsp_query(*openssl_unknown) is False + assert mock_log.debug.call_count == 1 + assert mock_log.warning.call_count == 0 + assert ocsp._translate_ocsp_query(*openssl_expired_ocsp) is False + assert mock_log.debug.call_count == 2 + assert ocsp._translate_ocsp_query(*openssl_broken) is False + assert mock_log.warning.call_count == 1 mock_log.info.call_count = 0 - self.assertIs(ocsp._translate_ocsp_query(*openssl_revoked), True) - self.assertEqual(mock_log.info.call_count, 0) - self.assertIs(ocsp._translate_ocsp_query(*openssl_expired_ocsp_revoked), True) - self.assertEqual(mock_log.info.call_count, 1) + assert ocsp._translate_ocsp_query(*openssl_revoked) is True + assert mock_log.info.call_count == 0 + assert ocsp._translate_ocsp_query(*openssl_expired_ocsp_revoked) is True + assert mock_log.info.call_count == 1 class OSCPTestCryptography(unittest.TestCase): @@ -159,7 +159,7 @@ class OSCPTestCryptography(unittest.TestCase): def test_revoke(self): with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertTrue(revoked) + assert revoked def test_responder_is_issuer(self): issuer = x509.load_pem_x509_certificate( @@ -179,11 +179,11 @@ class OSCPTestCryptography(unittest.TestCase): # Here responder and issuer are the same. So only the signature of the OCSP # response is checked (using the issuer/responder public key). - self.assertEqual(mocks['mock_check'].call_count, 2) - self.assertEqual(mocks['mock_check'].call_args_list[0][0][0].public_numbers(), - issuer.public_key().public_numbers()) - self.assertEqual(mocks['mock_check'].call_args_list[1][0][0].public_numbers(), - issuer.public_key().public_numbers()) + assert mocks['mock_check'].call_count == 2 + assert mocks['mock_check'].call_args_list[0][0][0].public_numbers() == \ + issuer.public_key().public_numbers() + assert mocks['mock_check'].call_args_list[1][0][0].public_numbers() == \ + issuer.public_key().public_numbers() def test_responder_is_authorized_delegate(self): issuer = x509.load_pem_x509_certificate( @@ -206,32 +206,32 @@ class OSCPTestCryptography(unittest.TestCase): # Here responder and issuer are not the same. Two signatures will be checked then, # first to verify the responder cert (using the issuer public key), second to # to verify the OCSP response itself (using the responder public key). - self.assertEqual(mocks['mock_check'].call_count, 4) - self.assertEqual(mocks['mock_check'].call_args_list[0][0][0].public_numbers(), - issuer.public_key().public_numbers()) - self.assertEqual(mocks['mock_check'].call_args_list[1][0][0].public_numbers(), - responder.public_key().public_numbers()) - self.assertEqual(mocks['mock_check'].call_args_list[2][0][0].public_numbers(), - issuer.public_key().public_numbers()) - self.assertEqual(mocks['mock_check'].call_args_list[3][0][0].public_numbers(), - responder.public_key().public_numbers()) + assert mocks['mock_check'].call_count == 4 + assert mocks['mock_check'].call_args_list[0][0][0].public_numbers() == \ + issuer.public_key().public_numbers() + assert mocks['mock_check'].call_args_list[1][0][0].public_numbers() == \ + responder.public_key().public_numbers() + assert mocks['mock_check'].call_args_list[2][0][0].public_numbers() == \ + issuer.public_key().public_numbers() + assert mocks['mock_check'].call_args_list[3][0][0].public_numbers() == \ + responder.public_key().public_numbers() def test_revoke_resiliency(self): # Server return an invalid HTTP response with _ocsp_mock(ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.SUCCESSFUL, http_status_code=400): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertIs(revoked, False) + assert revoked is False # OCSP response in invalid with _ocsp_mock(ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.UNAUTHORIZED): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertIs(revoked, False) + assert revoked is False # OCSP response is valid, but certificate status is unknown with _ocsp_mock(ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.SUCCESSFUL): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertIs(revoked, False) + assert revoked is False # The OCSP response says that the certificate is revoked, but certificate # does not contain the OCSP extension. @@ -240,32 +240,32 @@ class OSCPTestCryptography(unittest.TestCase): side_effect=x509.ExtensionNotFound( 'Not found', x509.AuthorityInformationAccessOID.OCSP)): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertIs(revoked, False) + assert revoked is False # OCSP response uses an unsupported signature. with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL, check_signature_side_effect=UnsupportedAlgorithm('foo')): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertIs(revoked, False) + assert revoked is False # OSCP signature response is invalid. with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL, check_signature_side_effect=InvalidSignature('foo')): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertIs(revoked, False) + assert revoked is False # Assertion error on OCSP response validity with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL, check_signature_side_effect=AssertionError('foo')): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertIs(revoked, False) + assert revoked is False # No responder cert in OCSP response with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) as mocks: mocks['mock_response'].return_value.certificates = [] revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertIs(revoked, False) + assert revoked is False # Responder cert is not signed by certificate issuer with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, @@ -274,7 +274,7 @@ class OSCPTestCryptography(unittest.TestCase): mocks['mock_response'].return_value.certificates[0] = mock.Mock( issuer='fake', subject=cert.subject) revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertIs(revoked, False) + assert revoked is False with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL): # This mock is necessary to avoid the first call contained in _determine_ocsp_server @@ -285,7 +285,7 @@ class OSCPTestCryptography(unittest.TestCase): side_effect=x509.ExtensionNotFound( 'Not found', x509.AuthorityInformationAccessOID.OCSP)): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertIs(revoked, False) + assert revoked is False @contextlib.contextmanager diff --git a/certbot/tests/plugins/common_test.py b/certbot/tests/plugins/common_test.py index 00f9f1c26..4a0af7c5e 100644 --- a/certbot/tests/plugins/common_test.py +++ b/certbot/tests/plugins/common_test.py @@ -29,15 +29,15 @@ class NamespaceFunctionsTest(unittest.TestCase): def test_option_namespace(self): from certbot.plugins.common import option_namespace - self.assertEqual("foo-", option_namespace("foo")) + assert "foo-" == option_namespace("foo") def test_dest_namespace(self): from certbot.plugins.common import dest_namespace - self.assertEqual("foo_", dest_namespace("foo")) + assert "foo_" == dest_namespace("foo") def test_dest_namespace_with_dashes(self): from certbot.plugins.common import dest_namespace - self.assertEqual("foo_bar_", dest_namespace("foo-bar")) + assert "foo_bar_" == dest_namespace("foo-bar") class PluginTest(unittest.TestCase): @@ -62,24 +62,24 @@ class PluginTest(unittest.TestCase): self.plugin = MockPlugin(config=self.config, name="mock") def test_init(self): - self.assertEqual("mock", self.plugin.name) - self.assertEqual(self.config, self.plugin.config) + assert "mock" == self.plugin.name + assert self.config == self.plugin.config def test_option_namespace(self): - self.assertEqual("mock-", self.plugin.option_namespace) + assert "mock-" == self.plugin.option_namespace def test_option_name(self): - self.assertEqual("mock-foo_bar", self.plugin.option_name("foo_bar")) + assert "mock-foo_bar" == self.plugin.option_name("foo_bar") def test_dest_namespace(self): - self.assertEqual("mock_", self.plugin.dest_namespace) + assert "mock_" == self.plugin.dest_namespace def test_dest(self): - self.assertEqual("mock_foo_bar", self.plugin.dest("foo-bar")) - self.assertEqual("mock_foo_bar", self.plugin.dest("foo_bar")) + assert "mock_foo_bar" == self.plugin.dest("foo-bar") + assert "mock_foo_bar" == self.plugin.dest("foo_bar") def test_conf(self): - self.assertEqual(self.config.mock_foo_bar, self.plugin.conf("foo-bar")) + assert self.config.mock_foo_bar == self.plugin.conf("foo-bar") def test_inject_parser_options(self): parser = mock.MagicMock() @@ -90,11 +90,11 @@ class PluginTest(unittest.TestCase): "--mock-foo-bar", dest="different_to_foo_bar", x=1, y=None) def test_fallback_auth_hint(self): - self.assertIn("the mock plugin completed the required dns-01 challenges", - self.plugin.auth_hint([acme_util.DNS01_A, acme_util.DNS01_A])) - self.assertIn("the mock plugin completed the required dns-01 and http-01 challenges", + assert "the mock plugin completed the required dns-01 challenges" in \ + self.plugin.auth_hint([acme_util.DNS01_A, acme_util.DNS01_A]) + assert "the mock plugin completed the required dns-01 and http-01 challenges" in \ self.plugin.auth_hint([acme_util.DNS01_A, acme_util.HTTP01_A, - acme_util.DNS01_A])) + acme_util.DNS01_A]) class InstallerTest(test_util.ConfigTestCase): @@ -174,12 +174,12 @@ class InstallerTest(test_util.ConfigTestCase): installer_func(*passed_args, **passed_kwargs) reverter_func.assert_called_once_with(*passed_args, **passed_kwargs) reverter_func.side_effect = errors.ReverterError - self.assertRaises( - errors.PluginError, installer_func, *passed_args, **passed_kwargs) + with pytest.raises(errors.PluginError): + installer_func(*passed_args, **passed_kwargs) def test_install_ssl_dhparams(self): self.installer.install_ssl_dhparams() - self.assertTrue(os.path.isfile(self.installer.ssl_dhparams)) + assert os.path.isfile(self.installer.ssl_dhparams) def _current_ssl_dhparams_hash(self): from certbot._internal.constants import SSL_DHPARAMS_SRC @@ -187,9 +187,9 @@ class InstallerTest(test_util.ConfigTestCase): def test_current_file_hash_in_all_hashes(self): from certbot._internal.constants import ALL_SSL_DHPARAMS_HASHES - self.assertIn(self._current_ssl_dhparams_hash(), ALL_SSL_DHPARAMS_HASHES, - "Constants.ALL_SSL_DHPARAMS_HASHES must be appended" - " with the sha256 hash of self.config.ssl_dhparams when it is updated.") + assert self._current_ssl_dhparams_hash() in ALL_SSL_DHPARAMS_HASHES, \ + "Constants.ALL_SSL_DHPARAMS_HASHES must be appended" \ + " with the sha256 hash of self.config.ssl_dhparams when it is updated." class AddrTest(unittest.TestCase): @@ -207,53 +207,53 @@ class AddrTest(unittest.TestCase): self.addr8 = Addr.fromstring("[fe00:1:2:3:4:5:6:7:8:9]:8080") def test_fromstring(self): - self.assertEqual(self.addr1.get_addr(), "192.168.1.1") - self.assertEqual(self.addr1.get_port(), "") - self.assertEqual(self.addr2.get_addr(), "192.168.1.1") - self.assertEqual(self.addr2.get_port(), "*") - self.assertEqual(self.addr3.get_addr(), "192.168.1.1") - self.assertEqual(self.addr3.get_port(), "80") - self.assertEqual(self.addr4.get_addr(), "[fe00::1]") - self.assertEqual(self.addr4.get_port(), "") - self.assertEqual(self.addr5.get_addr(), "[fe00::1]") - self.assertEqual(self.addr5.get_port(), "*") - self.assertEqual(self.addr6.get_addr(), "[fe00::1]") - self.assertEqual(self.addr6.get_port(), "80") - self.assertEqual(self.addr6.get_ipv6_exploded(), - "fe00:0:0:0:0:0:0:1") - self.assertEqual(self.addr1.get_ipv6_exploded(), - "") - self.assertEqual(self.addr7.get_port(), "5") - self.assertEqual(self.addr8.get_ipv6_exploded(), - "fe00:1:2:3:4:5:6:7") + assert self.addr1.get_addr() == "192.168.1.1" + assert self.addr1.get_port() == "" + assert self.addr2.get_addr() == "192.168.1.1" + assert self.addr2.get_port() == "*" + assert self.addr3.get_addr() == "192.168.1.1" + assert self.addr3.get_port() == "80" + assert self.addr4.get_addr() == "[fe00::1]" + assert self.addr4.get_port() == "" + assert self.addr5.get_addr() == "[fe00::1]" + assert self.addr5.get_port() == "*" + assert self.addr6.get_addr() == "[fe00::1]" + assert self.addr6.get_port() == "80" + assert self.addr6.get_ipv6_exploded() == \ + "fe00:0:0:0:0:0:0:1" + assert self.addr1.get_ipv6_exploded() == \ + "" + assert self.addr7.get_port() == "5" + assert self.addr8.get_ipv6_exploded() == \ + "fe00:1:2:3:4:5:6:7" def test_str(self): - self.assertEqual(str(self.addr1), "192.168.1.1") - self.assertEqual(str(self.addr2), "192.168.1.1:*") - self.assertEqual(str(self.addr3), "192.168.1.1:80") - self.assertEqual(str(self.addr4), "[fe00::1]") - self.assertEqual(str(self.addr5), "[fe00::1]:*") - self.assertEqual(str(self.addr6), "[fe00::1]:80") + assert str(self.addr1) == "192.168.1.1" + assert str(self.addr2) == "192.168.1.1:*" + assert str(self.addr3) == "192.168.1.1:80" + assert str(self.addr4) == "[fe00::1]" + assert str(self.addr5) == "[fe00::1]:*" + assert str(self.addr6) == "[fe00::1]:80" def test_get_addr_obj(self): - self.assertEqual(str(self.addr1.get_addr_obj("443")), "192.168.1.1:443") - self.assertEqual(str(self.addr2.get_addr_obj("")), "192.168.1.1") - self.assertEqual(str(self.addr1.get_addr_obj("*")), "192.168.1.1:*") - self.assertEqual(str(self.addr4.get_addr_obj("443")), "[fe00::1]:443") - self.assertEqual(str(self.addr5.get_addr_obj("")), "[fe00::1]") - self.assertEqual(str(self.addr4.get_addr_obj("*")), "[fe00::1]:*") + assert str(self.addr1.get_addr_obj("443")) == "192.168.1.1:443" + assert str(self.addr2.get_addr_obj("")) == "192.168.1.1" + assert str(self.addr1.get_addr_obj("*")) == "192.168.1.1:*" + assert str(self.addr4.get_addr_obj("443")) == "[fe00::1]:443" + assert str(self.addr5.get_addr_obj("")) == "[fe00::1]" + assert str(self.addr4.get_addr_obj("*")) == "[fe00::1]:*" def test_eq(self): - self.assertEqual(self.addr1, self.addr2.get_addr_obj("")) - self.assertNotEqual(self.addr1, self.addr2) - self.assertNotEqual(self.addr1, 3333) + assert self.addr1 == self.addr2.get_addr_obj("") + assert self.addr1 != self.addr2 + assert self.addr1 != 3333 - self.assertEqual(self.addr4, self.addr4.get_addr_obj("")) - self.assertNotEqual(self.addr4, self.addr5) - self.assertNotEqual(self.addr4, 3333) + assert self.addr4 == self.addr4.get_addr_obj("") + assert self.addr4 != self.addr5 + assert self.addr4 != 3333 from certbot.plugins.common import Addr - self.assertEqual(self.addr4, Addr.fromstring("[fe00:0:0::1]")) - self.assertEqual(self.addr4, Addr.fromstring("[fe00:0::0:0:1]")) + assert self.addr4 == Addr.fromstring("[fe00:0:0::1]") + assert self.addr4 == Addr.fromstring("[fe00:0::0:0:1]") def test_set_inclusion(self): @@ -263,14 +263,14 @@ class AddrTest(unittest.TestCase): addr2b = Addr.fromstring("192.168.1.1:*") set_b = {addr1b, addr2b} - self.assertEqual(set_a, set_b) + assert set_a == set_b set_c = {self.addr4, self.addr5} addr4b = Addr.fromstring("[fe00::1]") addr5b = Addr.fromstring("[fe00::1]:*") set_d = {addr4b, addr5b} - self.assertEqual(set_c, set_d) + assert set_c == set_d class ChallengePerformerTest(unittest.TestCase): @@ -284,11 +284,12 @@ class ChallengePerformerTest(unittest.TestCase): def test_add_chall(self): self.performer.add_chall(ACHALL, 0) - self.assertEqual(1, len(self.performer.achalls)) - self.assertEqual([0], self.performer.indices) + assert 1 == len(self.performer.achalls) + assert [0] == self.performer.indices def test_perform(self): - self.assertRaises(NotImplementedError, self.performer.perform) + with pytest.raises(NotImplementedError): + self.performer.perform() class InstallVersionControlledFileTest(test_util.TempDirTestCase): @@ -317,12 +318,12 @@ class InstallVersionControlledFileTest(test_util.TempDirTestCase): return crypto_util.sha256sum(self.source_path) def _assert_current_file(self): - self.assertTrue(os.path.isfile(self.dest_path)) - self.assertEqual(crypto_util.sha256sum(self.dest_path), - self._current_file_hash()) + assert os.path.isfile(self.dest_path) + assert crypto_util.sha256sum(self.dest_path) == \ + self._current_file_hash() def test_no_file(self): - self.assertFalse(os.path.isfile(self.dest_path)) + assert not os.path.isfile(self.dest_path) self._call() self._assert_current_file() @@ -343,12 +344,12 @@ class InstallVersionControlledFileTest(test_util.TempDirTestCase): mod_ssl_conf.write("a new line for the wrong hash\n") with mock.patch("certbot.plugins.common.logger") as mock_logger: self._call() - self.assertIs(mock_logger.warning.called, False) - self.assertTrue(os.path.isfile(self.dest_path)) - self.assertEqual(crypto_util.sha256sum(self.source_path), - self._current_file_hash()) - self.assertNotEqual(crypto_util.sha256sum(self.dest_path), - self._current_file_hash()) + assert mock_logger.warning.called is False + assert os.path.isfile(self.dest_path) + assert crypto_util.sha256sum(self.source_path) == \ + self._current_file_hash() + assert crypto_util.sha256sum(self.dest_path) != \ + self._current_file_hash() def test_manually_modified_past_file_warns(self): with open(self.dest_path, "a") as mod_ssl_conf: @@ -357,15 +358,15 @@ class InstallVersionControlledFileTest(test_util.TempDirTestCase): f.write("hashofanoldversion") with mock.patch("certbot.plugins.common.logger") as mock_logger: self._call() - self.assertEqual(mock_logger.warning.call_args[0][0], - "%s has been manually modified; updated file " - "saved to %s. We recommend updating %s for security purposes.") - self.assertEqual(crypto_util.sha256sum(self.source_path), - self._current_file_hash()) + assert mock_logger.warning.call_args[0][0] == \ + "%s has been manually modified; updated file " \ + "saved to %s. We recommend updating %s for security purposes." + assert crypto_util.sha256sum(self.source_path) == \ + self._current_file_hash() # only print warning once with mock.patch("certbot.plugins.common.logger") as mock_logger: self._call() - self.assertIs(mock_logger.warning.called, False) + assert mock_logger.warning.called is False if __name__ == "__main__": sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/plugins/disco_test.py b/certbot/tests/plugins/disco_test.py index a3b69ff0c..0a0fd9826 100644 --- a/certbot/tests/plugins/disco_test.py +++ b/certbot/tests/plugins/disco_test.py @@ -55,68 +55,64 @@ class PluginEntryPointTest(unittest.TestCase): } for entry_point, name in names.items(): - self.assertEqual( - name, PluginEntryPoint.entry_point_to_plugin_name(entry_point)) + assert name == PluginEntryPoint.entry_point_to_plugin_name(entry_point) def test_description(self): - self.assertIn("server locally", self.plugin_ep.description) + assert "server locally" in self.plugin_ep.description def test_description_with_name(self): self.plugin_ep.plugin_cls = mock.MagicMock(description="Desc") - self.assertEqual( - "Desc (sa)", self.plugin_ep.description_with_name) + assert "Desc (sa)" == self.plugin_ep.description_with_name def test_long_description(self): self.plugin_ep.plugin_cls = mock.MagicMock( long_description="Long desc") - self.assertEqual( - "Long desc", self.plugin_ep.long_description) + assert "Long desc" == self.plugin_ep.long_description def test_long_description_nonexistent(self): self.plugin_ep.plugin_cls = mock.MagicMock( description="Long desc not found", spec=["description"]) - self.assertEqual( - "Long desc not found", self.plugin_ep.long_description) + assert "Long desc not found" == self.plugin_ep.long_description def test_ifaces(self): - self.assertTrue(self.plugin_ep.ifaces((interfaces.Authenticator,))) - self.assertFalse(self.plugin_ep.ifaces((interfaces.Installer,))) - self.assertFalse(self.plugin_ep.ifaces(( - interfaces.Installer, interfaces.Authenticator))) + assert self.plugin_ep.ifaces((interfaces.Authenticator,)) + assert not self.plugin_ep.ifaces((interfaces.Installer,)) + assert not self.plugin_ep.ifaces(( + interfaces.Installer, interfaces.Authenticator)) def test__init__(self): - self.assertIs(self.plugin_ep.initialized, False) - self.assertIs(self.plugin_ep.prepared, False) - self.assertIs(self.plugin_ep.misconfigured, False) - self.assertIs(self.plugin_ep.available, False) - self.assertIsNone(self.plugin_ep.problem) - self.assertIs(self.plugin_ep.entry_point, EP_SA) - self.assertEqual("sa", self.plugin_ep.name) + assert self.plugin_ep.initialized is False + assert self.plugin_ep.prepared is False + assert self.plugin_ep.misconfigured is False + assert self.plugin_ep.available is False + assert self.plugin_ep.problem is None + assert self.plugin_ep.entry_point is EP_SA + assert "sa" == self.plugin_ep.name - self.assertIs(self.plugin_ep.plugin_cls, standalone.Authenticator) + assert self.plugin_ep.plugin_cls is standalone.Authenticator def test_init(self): config = mock.MagicMock() plugin = self.plugin_ep.init(config=config) - self.assertIs(self.plugin_ep.initialized, True) - self.assertIs(plugin.config, config) + assert self.plugin_ep.initialized is True + assert plugin.config is config # memoize! - self.assertIs(self.plugin_ep.init(), plugin) - self.assertIs(plugin.config, config) + assert self.plugin_ep.init() is plugin + assert plugin.config is config # try to give different config - self.assertIs(self.plugin_ep.init(123), plugin) - self.assertIs(plugin.config, config) + assert self.plugin_ep.init(123) is plugin + assert plugin.config is config - self.assertIs(self.plugin_ep.prepared, False) - self.assertIs(self.plugin_ep.misconfigured, False) - self.assertIs(self.plugin_ep.available, False) + assert self.plugin_ep.prepared is False + assert self.plugin_ep.misconfigured is False + assert self.plugin_ep.available is False def test_prepare(self): config = mock.MagicMock() self.plugin_ep.init(config=config) self.plugin_ep.prepare() - self.assertTrue(self.plugin_ep.prepared) - self.assertIs(self.plugin_ep.misconfigured, False) + assert self.plugin_ep.prepared + assert self.plugin_ep.misconfigured is False # output doesn't matter that much, just test if it runs str(self.plugin_ep) @@ -126,41 +122,40 @@ class PluginEntryPointTest(unittest.TestCase): plugin.prepare.side_effect = errors.MisconfigurationError # pylint: disable=protected-access self.plugin_ep._initialized = plugin - self.assertIsInstance(self.plugin_ep.prepare(), - errors.MisconfigurationError) - self.assertTrue(self.plugin_ep.prepared) - self.assertTrue(self.plugin_ep.misconfigured) - self.assertIsInstance(self.plugin_ep.problem, errors.MisconfigurationError) - self.assertTrue(self.plugin_ep.available) + assert isinstance(self.plugin_ep.prepare(), errors.MisconfigurationError) + assert self.plugin_ep.prepared + assert self.plugin_ep.misconfigured + assert isinstance(self.plugin_ep.problem, errors.MisconfigurationError) + assert self.plugin_ep.available def test_prepare_no_installation(self): plugin = mock.MagicMock() plugin.prepare.side_effect = errors.NoInstallationError # pylint: disable=protected-access self.plugin_ep._initialized = plugin - self.assertIsInstance(self.plugin_ep.prepare(), errors.NoInstallationError) - self.assertIs(self.plugin_ep.prepared, True) - self.assertIs(self.plugin_ep.misconfigured, False) - self.assertIs(self.plugin_ep.available, False) + assert isinstance(self.plugin_ep.prepare(), errors.NoInstallationError) + assert self.plugin_ep.prepared is True + assert self.plugin_ep.misconfigured is False + assert self.plugin_ep.available is False def test_prepare_generic_plugin_error(self): plugin = mock.MagicMock() plugin.prepare.side_effect = errors.PluginError # pylint: disable=protected-access self.plugin_ep._initialized = plugin - self.assertIsInstance(self.plugin_ep.prepare(), errors.PluginError) - self.assertTrue(self.plugin_ep.prepared) - self.assertIs(self.plugin_ep.misconfigured, False) - self.assertIs(self.plugin_ep.available, False) + assert isinstance(self.plugin_ep.prepare(), errors.PluginError) + assert self.plugin_ep.prepared + assert self.plugin_ep.misconfigured is False + assert self.plugin_ep.available is False def test_str(self): output = str(self.plugin_ep) - self.assertIn("Authenticator", output) - self.assertNotIn("Installer", output) - self.assertIn("Plugin", output) + assert "Authenticator" in output + assert "Installer" not in output + assert "Plugin" in output def test_repr(self): - self.assertEqual("PluginEntryPoint#sa", repr(self.plugin_ep)) + assert "PluginEntryPoint#sa" == repr(self.plugin_ep) class PluginsRegistryTest(unittest.TestCase): @@ -191,46 +186,44 @@ class PluginsRegistryTest(unittest.TestCase): standalone.Authenticator, webroot.Authenticator, null.Installer, null.Installer] plugins = PluginsRegistry.find_all() - self.assertIs(plugins["sa"].plugin_cls, standalone.Authenticator) - self.assertIs(plugins["sa"].entry_point, EP_SA) - self.assertIs(plugins["wr"].plugin_cls, webroot.Authenticator) - self.assertIs(plugins["wr"].entry_point, EP_WR) - self.assertIs(plugins["ep1"].plugin_cls, null.Installer) - self.assertIs(plugins["ep1"].entry_point, self.ep1) - self.assertNotIn("p1:ep1", plugins) + assert plugins["sa"].plugin_cls is standalone.Authenticator + assert plugins["sa"].entry_point is EP_SA + assert plugins["wr"].plugin_cls is webroot.Authenticator + assert plugins["wr"].entry_point is EP_WR + assert plugins["ep1"].plugin_cls is null.Installer + assert plugins["ep1"].entry_point is self.ep1 + assert "p1:ep1" not in plugins def test_getitem(self): - self.assertEqual(self.plugin_ep, self.reg["mock"]) + assert self.plugin_ep == self.reg["mock"] def test_iter(self): - self.assertEqual(["mock"], list(self.reg)) + assert ["mock"] == list(self.reg) def test_len(self): - self.assertEqual(0, len(self._create_new_registry({}))) - self.assertEqual(1, len(self.reg)) + assert 0 == len(self._create_new_registry({})) + assert 1 == len(self.reg) def test_init(self): self.plugin_ep.init.return_value = "baz" - self.assertEqual(["baz"], self.reg.init("bar")) + assert ["baz"] == self.reg.init("bar") self.plugin_ep.init.assert_called_once_with("bar") def test_filter(self): - self.assertEqual( - self.plugins, - self.reg.filter(lambda p_ep: p_ep.name.startswith("m"))) - self.assertEqual( - {}, self.reg.filter(lambda p_ep: p_ep.name.startswith("b"))) + assert self.plugins == \ + self.reg.filter(lambda p_ep: p_ep.name.startswith("m")) + assert {} == self.reg.filter(lambda p_ep: p_ep.name.startswith("b")) def test_ifaces(self): self.plugin_ep.ifaces.return_value = True # pylint: disable=protected-access - self.assertEqual(self.plugins, self.reg.ifaces()._plugins) + assert self.plugins == self.reg.ifaces()._plugins self.plugin_ep.ifaces.return_value = False - self.assertEqual({}, self.reg.ifaces()._plugins) + assert {} == self.reg.ifaces()._plugins def test_prepare(self): self.plugin_ep.prepare.return_value = "baz" - self.assertEqual(["baz"], self.reg.prepare()) + assert ["baz"] == self.reg.prepare() self.plugin_ep.prepare.assert_called_once_with() def test_prepare_order(self): @@ -243,33 +236,32 @@ class PluginsRegistryTest(unittest.TestCase): reg.prepare() # order of prepare calls must be sorted to prevent deadlock # caused by plugins acquiring locks during prepare - self.assertEqual(order, sorted(string.ascii_letters)) + assert order == sorted(string.ascii_letters) def test_available(self): self.plugin_ep.available = True # pylint: disable=protected-access - self.assertEqual(self.plugins, self.reg.available()._plugins) + assert self.plugins == self.reg.available()._plugins self.plugin_ep.available = False - self.assertEqual({}, self.reg.available()._plugins) + assert {} == self.reg.available()._plugins def test_find_init(self): - self.assertIsNone(self.reg.find_init(mock.Mock())) + assert self.reg.find_init(mock.Mock()) is None self.plugin_ep.initialized = True - self.assertIs( - self.reg.find_init(self.plugin_ep.init()), self.plugin_ep) + assert self.reg.find_init(self.plugin_ep.init()) is self.plugin_ep def test_repr(self): self.plugin_ep.__repr__ = lambda _: "PluginEntryPoint#mock" - self.assertEqual("PluginsRegistry(PluginEntryPoint#mock)", - repr(self.reg)) + assert "PluginsRegistry(PluginEntryPoint#mock)" == \ + repr(self.reg) def test_str(self): - self.assertEqual("No plugins", str(self._create_new_registry({}))) + assert "No plugins" == str(self._create_new_registry({})) self.plugin_ep.__str__ = lambda _: "Mock" - self.assertEqual("Mock", str(self.reg)) + assert "Mock" == str(self.reg) plugins = {self.plugin_ep.name: self.plugin_ep, "foo": "Bar"} reg = self._create_new_registry(plugins) - self.assertEqual("Bar\n\nMock", str(reg)) + assert "Bar\n\nMock" == str(reg) if __name__ == "__main__": diff --git a/certbot/tests/plugins/dns_common_test.py b/certbot/tests/plugins/dns_common_test.py index 19a359541..c74910d40 100644 --- a/certbot/tests/plugins/dns_common_test.py +++ b/certbot/tests/plugins/dns_common_test.py @@ -61,14 +61,15 @@ class DNSAuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthen (display_util.OK, "value",)) self.auth._configure("other_key", "") - self.assertEqual(self.auth.config.fake_other_key, "value") + assert self.auth.config.fake_other_key == "value" @test_util.patch_display_util() def test_prompt_canceled(self, mock_get_utility): mock_display = mock_get_utility() mock_display.input.side_effect = ((display_util.CANCEL, "c",),) - self.assertRaises(errors.PluginError, self.auth._configure, "other_key", "") + with pytest.raises(errors.PluginError): + self.auth._configure("other_key", "") @test_util.patch_display_util() def test_prompt_file(self, mock_get_utility): @@ -82,14 +83,15 @@ class DNSAuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthen (display_util.OK, path,)) self.auth._configure_file("file_path", "") - self.assertEqual(self.auth.config.fake_file_path, path) + assert self.auth.config.fake_file_path == path @test_util.patch_display_util() def test_prompt_file_canceled(self, mock_get_utility): mock_display = mock_get_utility() mock_display.directory_select.side_effect = ((display_util.CANCEL, "c",),) - self.assertRaises(errors.PluginError, self.auth._configure_file, "file_path", "") + with pytest.raises(errors.PluginError): + self.auth._configure_file("file_path", "") def test_configure_credentials(self): path = os.path.join(self.tempdir, 'file.ini') @@ -98,7 +100,7 @@ class DNSAuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthen credentials = self.auth._configure_credentials("credentials", "", {"test": ""}) - self.assertEqual(credentials.conf("test"), "value") + assert credentials.conf("test") == "value" @test_util.patch_display_util() def test_prompt_credentials(self, mock_get_utility): @@ -117,13 +119,11 @@ class DNSAuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthen (display_util.OK, path,)) credentials = self.auth._configure_credentials("credentials", "", {"test": ""}) - self.assertEqual(credentials.conf("test"), "value") + assert credentials.conf("test") == "value" def test_auth_hint(self): - self.assertIn( - 'try increasing --fake-propagation-seconds (currently 0 seconds).', + assert 'try increasing --fake-propagation-seconds (currently 0 seconds).' in \ self.auth.auth_hint([mock.MagicMock()]) - ) class CredentialsConfigurationTest(test_util.TempDirTestCase): @@ -147,13 +147,14 @@ class CredentialsConfigurationTest(test_util.TempDirTestCase): dns_test_common.write({"test": "value", "other": 1}, path) credentials_configuration = dns_common.CredentialsConfiguration(path) - self.assertEqual("value", credentials_configuration.conf("test")) - self.assertEqual("1", credentials_configuration.conf("other")) + assert "value" == credentials_configuration.conf("test") + assert "1" == credentials_configuration.conf("other") def test_nonexistent_file(self): path = os.path.join(self.tempdir, 'not-a-file.ini') - self.assertRaises(errors.PluginError, dns_common.CredentialsConfiguration, path) + with pytest.raises(errors.PluginError): + dns_common.CredentialsConfiguration(path) def test_valid_file_with_unsafe_permissions(self): log = self._MockLoggingHandler() @@ -164,7 +165,7 @@ class CredentialsConfigurationTest(test_util.TempDirTestCase): dns_common.CredentialsConfiguration(path) - self.assertEqual(1, len([_ for _ in log.messages['warning'] if _.startswith("Unsafe")])) + assert 1 == len([_ for _ in log.messages['warning'] if _.startswith("Unsafe")]) class CredentialsConfigurationRequireTest(test_util.TempDirTestCase): @@ -199,40 +200,37 @@ class CredentialsConfigurationRequireTest(test_util.TempDirTestCase): self._write({}) credentials_configuration = dns_common.CredentialsConfiguration(self.path) - self.assertRaises(errors.PluginError, credentials_configuration.require, {"test": ""}) + with pytest.raises(errors.PluginError): + credentials_configuration.require({"test": ""}) def test_blank(self): self._write({"test": ""}) credentials_configuration = dns_common.CredentialsConfiguration(self.path) - self.assertRaises(errors.PluginError, credentials_configuration.require, {"test": ""}) + with pytest.raises(errors.PluginError): + credentials_configuration.require({"test": ""}) def test_typo(self): self._write({"tets": "typo!"}) credentials_configuration = dns_common.CredentialsConfiguration(self.path) - self.assertRaises(errors.PluginError, credentials_configuration.require, {"test": ""}) + with pytest.raises(errors.PluginError): + credentials_configuration.require({"test": ""}) class DomainNameGuessTest(unittest.TestCase): def test_simple_case(self): - self.assertIn( - 'example.com', + assert 'example.com' in \ dns_common.base_domain_name_guesses("example.com") - ) def test_sub_domain(self): - self.assertIn( - 'example.com', + assert 'example.com' in \ dns_common.base_domain_name_guesses("foo.bar.baz.example.com") - ) def test_second_level_domain(self): - self.assertIn( - 'example.co.uk', + assert 'example.co.uk' in \ dns_common.base_domain_name_guesses("foo.bar.baz.example.co.uk") - ) if __name__ == "__main__": diff --git a/certbot/tests/plugins/enhancements_test.py b/certbot/tests/plugins/enhancements_test.py index 917b74db8..39734899c 100644 --- a/certbot/tests/plugins/enhancements_test.py +++ b/certbot/tests/plugins/enhancements_test.py @@ -34,31 +34,31 @@ class EnhancementTest(test_util.ConfigTestCase): self.config.auto_hsts = True self.config.something = True enabled = list(enhancements.enabled_enhancements(self.config)) - self.assertEqual(len(enabled), 2) - self.assertTrue([i for i in enabled if i["name"] == "autohsts"]) - self.assertTrue([i for i in enabled if i["name"] == "somethingelse"]) + assert len(enabled) == 2 + assert [i for i in enabled if i["name"] == "autohsts"] + assert [i for i in enabled if i["name"] == "somethingelse"] def test_are_requested(self): - self.assertEqual(len(list(enhancements.enabled_enhancements(self.config))), 0) - self.assertFalse(enhancements.are_requested(self.config)) + assert len(list(enhancements.enabled_enhancements(self.config))) == 0 + assert not enhancements.are_requested(self.config) self.config.auto_hsts = True - self.assertEqual(len(list(enhancements.enabled_enhancements(self.config))), 1) - self.assertTrue(enhancements.are_requested(self.config)) + assert len(list(enhancements.enabled_enhancements(self.config))) == 1 + assert enhancements.are_requested(self.config) def test_are_supported(self): self.config.auto_hsts = True unsupported = null.Installer(self.config, "null") - self.assertTrue(enhancements.are_supported(self.config, self.mockinstaller)) - self.assertFalse(enhancements.are_supported(self.config, unsupported)) + assert enhancements.are_supported(self.config, self.mockinstaller) + assert not enhancements.are_supported(self.config, unsupported) def test_enable(self): self.config.auto_hsts = True domains = ["example.com", "www.example.com"] lineage = "lineage" enhancements.enable(lineage, domains, self.mockinstaller, self.config) - self.assertTrue(self.mockinstaller.enable_autohsts.called) - self.assertEqual(self.mockinstaller.enable_autohsts.call_args[0], - (lineage, domains)) + assert self.mockinstaller.enable_autohsts.called + assert self.mockinstaller.enable_autohsts.call_args[0] == \ + (lineage, domains) if __name__ == '__main__': diff --git a/certbot/tests/plugins/manual_test.py b/certbot/tests/plugins/manual_test.py index 19064bc00..b4125c659 100644 --- a/certbot/tests/plugins/manual_test.py +++ b/certbot/tests/plugins/manual_test.py @@ -47,19 +47,21 @@ class AuthenticatorTest(test_util.TempDirTestCase): def test_prepare_no_hook_noninteractive(self): self.config.noninteractive_mode = True - self.assertRaises(errors.PluginError, self.auth.prepare) + with pytest.raises(errors.PluginError): + self.auth.prepare() def test_prepare_bad_hook(self): self.config.manual_auth_hook = os.path.abspath(os.sep) # is / on UNIX self.config.validate_hooks = True - self.assertRaises(errors.HookCommandNotFound, self.auth.prepare) + with pytest.raises(errors.HookCommandNotFound): + self.auth.prepare() def test_more_info(self): - self.assertIsInstance(self.auth.more_info(), str) + assert isinstance(self.auth.more_info(), str) def test_get_chall_pref(self): - self.assertEqual(self.auth.get_chall_pref('example.org'), - [challenges.HTTP01, challenges.DNS01]) + assert self.auth.get_chall_pref('example.org') == \ + [challenges.HTTP01, challenges.DNS01] def test_script_perform(self): self.config.manual_auth_hook = ( @@ -82,32 +84,28 @@ class AuthenticatorTest(test_util.TempDirTestCase): ','.join(achall.domain for achall in self.achalls), len(self.achalls) - self.achalls.index(self.http_achall) - 1) - self.assertEqual( - self.auth.perform(self.achalls), - [achall.response(achall.account_key) for achall in self.achalls]) - self.assertEqual( - self.auth.env[self.dns_achall]['CERTBOT_AUTH_OUTPUT'], - dns_expected) - self.assertEqual( - self.auth.env[self.http_achall]['CERTBOT_AUTH_OUTPUT'], - http_expected) + assert self.auth.perform(self.achalls) == \ + [achall.response(achall.account_key) for achall in self.achalls] + assert self.auth.env[self.dns_achall]['CERTBOT_AUTH_OUTPUT'] == \ + dns_expected + assert self.auth.env[self.http_achall]['CERTBOT_AUTH_OUTPUT'] == \ + http_expected # Successful hook output should be sent to notify - self.assertEqual(self.mock_get_display().notification.call_count, len(self.achalls)) + assert self.mock_get_display().notification.call_count == len(self.achalls) for i, (args, _) in enumerate(self.mock_get_display().notification.call_args_list): needle = textwrap.indent(self.auth.env[self.achalls[i]]['CERTBOT_AUTH_OUTPUT'], ' ') - self.assertIn(needle, args[0]) + assert needle in args[0] def test_manual_perform(self): - self.assertEqual( - self.auth.perform(self.achalls), - [achall.response(achall.account_key) for achall in self.achalls]) + assert self.auth.perform(self.achalls) == \ + [achall.response(achall.account_key) for achall in self.achalls] - self.assertEqual(self.mock_get_display().notification.call_count, len(self.achalls)) + assert self.mock_get_display().notification.call_count == len(self.achalls) for i, (args, kwargs) in enumerate(self.mock_get_display().notification.call_args_list): achall = self.achalls[i] - self.assertIn(achall.validation(achall.account_key), args[0]) - self.assertIs(kwargs['wrap'], False) + assert achall.validation(achall.account_key) in args[0] + assert kwargs['wrap'] is False def test_cleanup(self): self.config.manual_auth_hook = ('{0} -c "import sys; sys.stdout.write(\'foo\')"' @@ -117,47 +115,37 @@ class AuthenticatorTest(test_util.TempDirTestCase): for achall in self.achalls: self.auth.cleanup([achall]) - self.assertEqual(os.environ['CERTBOT_AUTH_OUTPUT'], 'foo') - self.assertEqual(os.environ['CERTBOT_DOMAIN'], achall.domain) + assert os.environ['CERTBOT_AUTH_OUTPUT'] == 'foo' + assert os.environ['CERTBOT_DOMAIN'] == achall.domain if isinstance(achall.chall, (challenges.HTTP01, challenges.DNS01)): - self.assertEqual( - os.environ['CERTBOT_VALIDATION'], - achall.validation(achall.account_key)) + assert os.environ['CERTBOT_VALIDATION'] == \ + achall.validation(achall.account_key) if isinstance(achall.chall, challenges.HTTP01): - self.assertEqual( - os.environ['CERTBOT_TOKEN'], - achall.chall.encode('token')) + assert os.environ['CERTBOT_TOKEN'] == \ + achall.chall.encode('token') else: - self.assertNotIn('CERTBOT_TOKEN', os.environ) + assert 'CERTBOT_TOKEN' not in os.environ def test_auth_hint_hook(self): self.config.manual_auth_hook = '/bin/true' - self.assertEqual( - self.auth.auth_hint([acme_util.DNS01_A, acme_util.HTTP01_A]), - 'The Certificate Authority failed to verify the DNS TXT records and challenge ' - 'files created by the --manual-auth-hook. Ensure that this hook is functioning ' - 'correctly and that it waits a sufficient duration of time for DNS propagation. ' + assert self.auth.auth_hint([acme_util.DNS01_A, acme_util.HTTP01_A]) == \ + 'The Certificate Authority failed to verify the DNS TXT records and challenge ' \ + 'files created by the --manual-auth-hook. Ensure that this hook is functioning ' \ + 'correctly and that it waits a sufficient duration of time for DNS propagation. ' \ 'Refer to "certbot --help manual" and the Certbot User Guide.' - ) - self.assertEqual( - self.auth.auth_hint([acme_util.HTTP01_A]), - 'The Certificate Authority failed to verify the challenge files created by the ' - '--manual-auth-hook. Ensure that this hook is functioning correctly. Refer to ' + assert self.auth.auth_hint([acme_util.HTTP01_A]) == \ + 'The Certificate Authority failed to verify the challenge files created by the ' \ + '--manual-auth-hook. Ensure that this hook is functioning correctly. Refer to ' \ '"certbot --help manual" and the Certbot User Guide.' - ) def test_auth_hint_no_hook(self): - self.assertEqual( - self.auth.auth_hint([acme_util.DNS01_A, acme_util.HTTP01_A]), - 'The Certificate Authority failed to verify the manually created DNS TXT records ' - 'and challenge files. Ensure that you created these in the correct location, or ' + assert self.auth.auth_hint([acme_util.DNS01_A, acme_util.HTTP01_A]) == \ + 'The Certificate Authority failed to verify the manually created DNS TXT records ' \ + 'and challenge files. Ensure that you created these in the correct location, or ' \ 'try waiting longer for DNS propagation on the next attempt.' - ) - self.assertEqual( - self.auth.auth_hint([acme_util.HTTP01_A, acme_util.HTTP01_A, acme_util.HTTP01_A]), - 'The Certificate Authority failed to verify the manually created challenge files. ' + assert self.auth.auth_hint([acme_util.HTTP01_A, acme_util.HTTP01_A, acme_util.HTTP01_A]) == \ + 'The Certificate Authority failed to verify the manually created challenge files. ' \ 'Ensure that you created these in the correct location.' - ) if __name__ == '__main__': diff --git a/certbot/tests/plugins/null_test.py b/certbot/tests/plugins/null_test.py index 64a5b0709..4740b7d87 100644 --- a/certbot/tests/plugins/null_test.py +++ b/certbot/tests/plugins/null_test.py @@ -14,9 +14,9 @@ class InstallerTest(unittest.TestCase): self.installer = Installer(config=mock.MagicMock(), name="null") def test_it(self): - self.assertIsInstance(self.installer.more_info(), str) - self.assertEqual([], self.installer.get_all_names()) - self.assertEqual([], self.installer.supported_enhancements()) + assert isinstance(self.installer.more_info(), str) + assert [] == self.installer.get_all_names() + assert [] == self.installer.supported_enhancements() if __name__ == "__main__": diff --git a/certbot/tests/plugins/selection_test.py b/certbot/tests/plugins/selection_test.py index 272cdb484..290965544 100644 --- a/certbot/tests/plugins/selection_test.py +++ b/certbot/tests/plugins/selection_test.py @@ -24,7 +24,7 @@ class ConveniencePickPluginTest(unittest.TestCase): with mock.patch("certbot._internal.plugins.selection.pick_plugin") as mock_p: mock_p.return_value = "foo" - self.assertEqual("foo", fun(config, default, plugins, "Question?")) + assert "foo" == fun(config, default, plugins, "Question?") mock_p.assert_called_once_with( config, default, plugins, "Question?", ifaces) @@ -60,14 +60,14 @@ class PickPluginTest(unittest.TestCase): def test_default_provided(self): self.default = "foo" self._call() - self.assertEqual(1, self.reg.filter.call_count) + assert 1 == self.reg.filter.call_count def test_no_default(self): self._call() - self.assertEqual(1, self.reg.visible().ifaces.call_count) + assert 1 == self.reg.visible().ifaces.call_count def test_no_candidate(self): - self.assertIsNone(self._call()) + assert self._call() is None def test_single(self): plugin_ep = mock.MagicMock() @@ -76,7 +76,7 @@ class PickPluginTest(unittest.TestCase): self.reg.visible().ifaces().available.return_value = { "bar": plugin_ep} - self.assertEqual("foo", self._call()) + assert "foo" == self._call() def test_single_misconfigured(self): plugin_ep = mock.MagicMock() @@ -85,7 +85,7 @@ class PickPluginTest(unittest.TestCase): self.reg.visible().ifaces().available.return_value = { "bar": plugin_ep} - self.assertIsNone(self._call()) + assert self._call() is None def test_multiple(self): plugin_ep = mock.MagicMock() @@ -96,7 +96,7 @@ class PickPluginTest(unittest.TestCase): } with mock.patch("certbot._internal.plugins.selection.choose_plugin") as mock_choose: mock_choose.return_value = plugin_ep - self.assertEqual("foo", self._call()) + assert "foo" == self._call() mock_choose.assert_called_once_with( [plugin_ep, plugin_ep], self.question) @@ -108,7 +108,7 @@ class PickPluginTest(unittest.TestCase): with mock.patch("certbot._internal.plugins.selection.choose_plugin") as mock_choose: mock_choose.return_value = None - self.assertIsNone(self._call()) + assert self._call() is None class ChoosePluginTest(unittest.TestCase): @@ -136,8 +136,8 @@ class ChoosePluginTest(unittest.TestCase): def test_selection(self, mock_util): mock_util().menu.side_effect = [(display_util.OK, 0), (display_util.OK, 1)] - self.assertEqual(self.mock_stand, self._call()) - self.assertEqual(mock_util().notification.call_count, 1) + assert self.mock_stand == self._call() + assert mock_util().notification.call_count == 1 @test_util.patch_display_util() def test_more_info(self, mock_util): @@ -145,12 +145,12 @@ class ChoosePluginTest(unittest.TestCase): (display_util.OK, 1), ] - self.assertEqual(self.mock_stand, self._call()) + assert self.mock_stand == self._call() @test_util.patch_display_util() def test_no_choice(self, mock_util): mock_util().menu.return_value = (display_util.CANCEL, 0) - self.assertIsNone(self._call()) + assert self._call() is None class GetUnpreparedInstallerTest(test_util.ConfigTestCase): @@ -177,23 +177,25 @@ class GetUnpreparedInstallerTest(test_util.ConfigTestCase): def test_no_installer_defined(self): self.config.configurator = None - self.assertIsNone(self._call()) + assert self._call() is None def test_no_available_installers(self): self.config.configurator = "apache" self.plugins = PluginsRegistry({}) - self.assertRaises(errors.PluginSelectionError, self._call) + with pytest.raises(errors.PluginSelectionError): + self._call() def test_get_plugin(self): self.config.configurator = "apache" installer = self._call() - self.assertIs(installer, self.mock_apache_plugin) + assert installer is self.mock_apache_plugin def test_multiple_installers_returned(self): self.config.configurator = "apache" # Two plugins with the same name self.mock_apache_fail_ep.check_name = lambda name: name == "apache" - self.assertRaises(errors.PluginSelectionError, self._call) + with pytest.raises(errors.PluginSelectionError): + self._call() class TestChooseConfiguratorPlugins(unittest.TestCase): @@ -230,37 +232,37 @@ class TestChooseConfiguratorPlugins(unittest.TestCase): # For certonly, setting either the nginx or apache configurators should # return both an installer and authenticator inst, auth = self._runWithArgs("certonly --nginx") - self.assertEqual(inst.name, "nginx") - self.assertEqual(auth.name, "nginx") + assert inst.name == "nginx" + assert auth.name == "nginx" inst, auth = self._runWithArgs("certonly --apache") - self.assertEqual(inst.name, "apache") - self.assertEqual(auth.name, "apache") + assert inst.name == "apache" + assert auth.name == "apache" def test_noninteractive_inst_arg(self): # For certonly, if an installer arg is set, it should be returned as expected inst, auth = self._runWithArgs("certonly -a nginx -i nginx") - self.assertEqual(inst.name, "nginx") - self.assertEqual(auth.name, "nginx") + assert inst.name == "nginx" + assert auth.name == "nginx" inst, auth = self._runWithArgs("certonly -a apache -i apache") - self.assertEqual(inst.name, "apache") - self.assertEqual(auth.name, "apache") + assert inst.name == "apache" + assert auth.name == "apache" # if no installer arg is set (or it's set to none), one shouldn't be returned inst, auth = self._runWithArgs("certonly -a nginx") - self.assertEqual(inst, None) - self.assertEqual(auth.name, "nginx") + assert inst == None + assert auth.name == "nginx" inst, auth = self._runWithArgs("certonly -a nginx -i none") - self.assertEqual(inst, None) - self.assertEqual(auth.name, "nginx") + assert inst == None + assert auth.name == "nginx" inst, auth = self._runWithArgs("certonly -a apache") - self.assertEqual(inst, None) - self.assertEqual(auth.name, "apache") + assert inst == None + assert auth.name == "apache" inst, auth = self._runWithArgs("certonly -a apache -i none") - self.assertEqual(inst, None) - self.assertEqual(auth.name, "apache") + assert inst == None + assert auth.name == "apache" if __name__ == "__main__": sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/plugins/standalone_test.py b/certbot/tests/plugins/standalone_test.py index 6e173ed79..7c2153a63 100644 --- a/certbot/tests/plugins/standalone_test.py +++ b/certbot/tests/plugins/standalone_test.py @@ -30,15 +30,15 @@ class ServerManagerTest(unittest.TestCase): self.mgr = ServerManager(self.certs, self.http_01_resources) def test_init(self): - self.assertIs(self.mgr.certs, self.certs) - self.assertIs(self.mgr.http_01_resources, self.http_01_resources) + assert self.mgr.certs is self.certs + assert self.mgr.http_01_resources is self.http_01_resources def _test_run_stop(self, challenge_type): server = self.mgr.run(port=0, challenge_type=challenge_type) port = server.getsocknames()[0][1] - self.assertEqual(self.mgr.running(), {port: server}) + assert self.mgr.running() == {port: server} self.mgr.stop(port=port) - self.assertEqual(self.mgr.running(), {}) + assert self.mgr.running() == {} def test_run_stop_http_01(self): self._test_run_stop(challenges.HTTP01) @@ -47,10 +47,10 @@ class ServerManagerTest(unittest.TestCase): server = self.mgr.run(port=0, challenge_type=challenges.HTTP01) port = server.getsocknames()[0][1] server2 = self.mgr.run(port=port, challenge_type=challenges.HTTP01) - self.assertEqual(self.mgr.running(), {port: server}) - self.assertIs(server, server2) + assert self.mgr.running() == {port: server} + assert server is server2 self.mgr.stop(port) - self.assertEqual(self.mgr.running(), {}) + assert self.mgr.running() == {} def test_run_bind_error(self): some_server = socket.socket(socket.AF_INET6) @@ -61,10 +61,10 @@ class ServerManagerTest(unittest.TestCase): maybe_another_server.bind(("", port)) except socket.error: pass - self.assertRaises( - errors.StandaloneBindError, self.mgr.run, port, + with pytest.raises(errors.StandaloneBindError): + self.mgr.run(port, challenge_type=challenges.HTTP01) - self.assertEqual(self.mgr.running(), {}) + assert self.mgr.running() == {} some_server.close() maybe_another_server.close() @@ -89,18 +89,18 @@ class AuthenticatorTest(unittest.TestCase): self.auth.servers = mock.MagicMock() def test_more_info(self): - self.assertIsInstance(self.auth.more_info(), str) + assert isinstance(self.auth.more_info(), str) def test_get_chall_pref(self): - self.assertEqual(self.auth.get_chall_pref(domain=None), - [challenges.HTTP01]) + assert self.auth.get_chall_pref(domain=None) == \ + [challenges.HTTP01] def test_perform(self): achalls = self._get_achalls() response = self.auth.perform(achalls) expected = [achall.response(achall.account_key) for achall in achalls] - self.assertEqual(response, expected) + assert response == expected @test_util.patch_display_util() def test_perform_eaddrinuse_retry(self, mock_get_utility): @@ -121,22 +121,24 @@ class AuthenticatorTest(unittest.TestCase): mock_yesno.return_value = False encountered_errno = errno.EADDRINUSE - self.assertRaises(errors.PluginError, self._fail_perform, encountered_errno) + with pytest.raises(errors.PluginError): + self._fail_perform(encountered_errno) self._assert_correct_yesno_call(mock_yesno) def _assert_correct_yesno_call(self, mock_yesno): yesno_args, yesno_kwargs = mock_yesno.call_args - self.assertIn("in use", yesno_args[0]) - self.assertFalse(yesno_kwargs.get("default", True)) + assert "in use" in yesno_args[0] + assert not yesno_kwargs.get("default", True) def test_perform_eacces(self): encountered_errno = errno.EACCES - self.assertRaises(errors.PluginError, self._fail_perform, encountered_errno) + with pytest.raises(errors.PluginError): + self._fail_perform(encountered_errno) def test_perform_unexpected_socket_error(self): encountered_errno = errno.ENOTCONN - self.assertRaises( - errors.StandaloneBindError, self._fail_perform, encountered_errno) + with pytest.raises(errors.StandaloneBindError): + self._fail_perform(encountered_errno) def _fail_perform(self, encountered_errno): error = errors.StandaloneBindError(mock.MagicMock(errno=encountered_errno), -1) @@ -161,29 +163,29 @@ class AuthenticatorTest(unittest.TestCase): self.auth.served["server2"].update(["chall2", "chall3"]) self.auth.cleanup(["chall1"]) - self.assertEqual(self.auth.served, { - "server1": set(), "server2": {"chall2", "chall3"}}) + assert self.auth.served == { + "server1": set(), "server2": {"chall2", "chall3"}} self.auth.servers.stop.assert_called_once_with(1) self.auth.servers.running.return_value = { 2: "server2", } self.auth.cleanup(["chall2"]) - self.assertEqual(self.auth.served, { - "server1": set(), "server2": {"chall3"}}) - self.assertEqual(1, self.auth.servers.stop.call_count) + assert self.auth.served == { + "server1": set(), "server2": {"chall3"}} + assert 1 == self.auth.servers.stop.call_count self.auth.cleanup(["chall3"]) - self.assertEqual(self.auth.served, { - "server1": set(), "server2": set()}) + assert self.auth.served == { + "server1": set(), "server2": set()} self.auth.servers.stop.assert_called_with(2) def test_auth_hint(self): self.config.http01_port = "80" self.config.http01_address = None - self.assertIn("on port 80", self.auth.auth_hint([])) + assert "on port 80" in self.auth.auth_hint([]) self.config.http01_address = "127.0.0.1" - self.assertIn("on 127.0.0.1:80", self.auth.auth_hint([])) + assert "on 127.0.0.1:80" in self.auth.auth_hint([]) if __name__ == "__main__": diff --git a/certbot/tests/plugins/storage_test.py b/certbot/tests/plugins/storage_test.py index ae4b575e0..a6f8f876d 100644 --- a/certbot/tests/plugins/storage_test.py +++ b/certbot/tests/plugins/storage_test.py @@ -37,8 +37,8 @@ class PluginStorageTest(test_util.ConfigTestCase): with mock.patch("builtins.open", mock_open): with mock.patch('certbot.compat.os.path.isfile', return_value=True): with mock.patch("certbot.reverter.util"): - self.assertRaises(errors.PluginStorageError, - self.plugin.storage._load) # pylint: disable=protected-access + with pytest.raises(errors.PluginStorageError): + self.plugin.storage._load() # pylint: disable=protected-access def test_load_errors_empty(self): with open(os.path.join(self.config.config_dir, ".pluginstorage.json"), "w") as fh: @@ -47,10 +47,10 @@ class PluginStorageTest(test_util.ConfigTestCase): # Should not error out but write a debug log line instead with mock.patch("certbot.reverter.util"): nocontent = self.plugin_cls(self.config, "mockplugin") - self.assertRaises(KeyError, - nocontent.storage.fetch, "value") - self.assertTrue(mock_log.called) - self.assertIn("no values loaded", mock_log.call_args[0][0]) + with pytest.raises(KeyError): + nocontent.storage.fetch("value") + assert mock_log.called + assert "no values loaded" in mock_log.call_args[0][0] def test_load_errors_corrupted(self): with open(os.path.join(self.config.config_dir, @@ -59,10 +59,9 @@ class PluginStorageTest(test_util.ConfigTestCase): with mock.patch("certbot.plugins.storage.logger.error") as mock_log: with mock.patch("certbot.reverter.util"): corrupted = self.plugin_cls(self.config, "mockplugin") - self.assertRaises(errors.PluginError, - corrupted.storage.fetch, - "value") - self.assertIn("is corrupted", mock_log.call_args[0][0]) + with pytest.raises(errors.PluginError): + corrupted.storage.fetch("value") + assert "is corrupted" in mock_log.call_args[0][0] def test_save_errors_cant_serialize(self): with mock.patch("certbot.plugins.storage.logger.error") as mock_log: @@ -70,9 +69,9 @@ class PluginStorageTest(test_util.ConfigTestCase): self.plugin.storage._initialized = True # pylint: disable=protected-access self.plugin.storage._storagepath = "/tmp/whatever" self.plugin.storage._data = self.plugin_cls # pylint: disable=protected-access - self.assertRaises(errors.PluginStorageError, - self.plugin.storage.save) - self.assertIn("Could not serialize", mock_log.call_args[0][0]) + with pytest.raises(errors.PluginStorageError): + self.plugin.storage.save() + assert "Could not serialize" in mock_log.call_args[0][0] def test_save_errors_unable_to_write_file(self): mock_open = mock.mock_open() @@ -82,25 +81,25 @@ class PluginStorageTest(test_util.ConfigTestCase): self.plugin.storage._data = {"valid": "data"} # pylint: disable=protected-access self.plugin.storage._initialized = True # pylint: disable=protected-access self.plugin.storage._storagepath = "/tmp/whatever" - self.assertRaises(errors.PluginStorageError, - self.plugin.storage.save) - self.assertIn("Could not write", mock_log.call_args[0][0]) + with pytest.raises(errors.PluginStorageError): + self.plugin.storage.save() + assert "Could not write" in mock_log.call_args[0][0] def test_save_uninitialized(self): with mock.patch("certbot.reverter.util"): - self.assertRaises(errors.PluginStorageError, - self.plugin_cls(self.config, "x").storage.save) + with pytest.raises(errors.PluginStorageError): + self.plugin_cls(self.config, "x").storage.save() def test_namespace_isolation(self): with mock.patch("certbot.reverter.util"): plugin1 = self.plugin_cls(self.config, "first") plugin2 = self.plugin_cls(self.config, "second") plugin1.storage.put("first_key", "first_value") - self.assertRaises(KeyError, - plugin2.storage.fetch, "first_key") - self.assertRaises(KeyError, - plugin2.storage.fetch, "first") - self.assertEqual(plugin1.storage.fetch("first_key"), "first_value") + with pytest.raises(KeyError): + plugin2.storage.fetch("first_key") + with pytest.raises(KeyError): + plugin2.storage.fetch("first") + assert plugin1.storage.fetch("first_key") == "first_value" def test_saved_state(self): self.plugin.storage.put("testkey", "testvalue") @@ -108,15 +107,15 @@ class PluginStorageTest(test_util.ConfigTestCase): self.plugin.storage.save() with mock.patch("certbot.reverter.util"): another = self.plugin_cls(self.config, "mockplugin") - self.assertEqual(another.storage.fetch("testkey"), "testvalue") + assert another.storage.fetch("testkey") == "testvalue" with open(os.path.join(self.config.config_dir, ".pluginstorage.json"), 'r') as fh: psdata = fh.read() psjson = json.loads(psdata) - self.assertIn("mockplugin", psjson.keys()) - self.assertEqual(len(psjson), 1) - self.assertEqual(psjson["mockplugin"]["testkey"], "testvalue") + assert "mockplugin" in psjson.keys() + assert len(psjson) == 1 + assert psjson["mockplugin"]["testkey"] == "testvalue" if __name__ == "__main__": diff --git a/certbot/tests/plugins/util_test.py b/certbot/tests/plugins/util_test.py index eabfe5fa3..bf5817c10 100644 --- a/certbot/tests/plugins/util_test.py +++ b/certbot/tests/plugins/util_test.py @@ -12,11 +12,10 @@ class GetPrefixTest(unittest.TestCase): """Tests for certbot.plugins.get_prefixes.""" def test_get_prefix(self): from certbot.plugins.util import get_prefixes - self.assertEqual( - get_prefixes('/a/b/c'), - [os.path.normpath(path) for path in ['/a/b/c', '/a/b', '/a', '/']]) - self.assertEqual(get_prefixes('/'), [os.path.normpath('/')]) - self.assertEqual(get_prefixes('a'), ['a']) + assert get_prefixes('/a/b/c') == \ + [os.path.normpath(path) for path in ['/a/b/c', '/a/b', '/a', '/']] + assert get_prefixes('/') == [os.path.normpath('/')] + assert get_prefixes('a') == ['a'] class PathSurgeryTest(unittest.TestCase): @@ -29,18 +28,18 @@ class PathSurgeryTest(unittest.TestCase): with mock.patch.dict('os.environ', all_path): with mock.patch('certbot.util.exe_exists') as mock_exists: mock_exists.return_value = True - self.assertIs(path_surgery("eg"), True) - self.assertEqual(mock_debug.call_count, 0) - self.assertEqual(os.environ["PATH"], all_path["PATH"]) + assert path_surgery("eg") is True + assert mock_debug.call_count == 0 + assert os.environ["PATH"] == all_path["PATH"] if os.name != 'nt': # This part is specific to Linux since on Windows no PATH surgery is ever done. no_path = {"PATH": "/tmp/"} with mock.patch.dict('os.environ', no_path): path_surgery("thingy") - self.assertEqual(mock_debug.call_count, 2 if os.name != 'nt' else 1) - self.assertIn("Failed to find", mock_debug.call_args[0][0]) - self.assertIn("/usr/local/bin", os.environ["PATH"]) - self.assertIn("/tmp", os.environ["PATH"]) + assert mock_debug.call_count == (2 if os.name != 'nt' else 1) + assert "Failed to find" in mock_debug.call_args[0][0] + assert "/usr/local/bin" in os.environ["PATH"] + assert "/tmp" in os.environ["PATH"] if __name__ == "__main__": diff --git a/certbot/tests/plugins/webroot_test.py b/certbot/tests/plugins/webroot_test.py index 210be36e6..2561ccaf1 100644 --- a/certbot/tests/plugins/webroot_test.py +++ b/certbot/tests/plugins/webroot_test.py @@ -58,13 +58,13 @@ class AuthenticatorTest(unittest.TestCase): def test_more_info(self): more_info = self.auth.more_info() - self.assertIsInstance(more_info, str) - self.assertIn(self.path, more_info) + assert isinstance(more_info, str) + assert self.path in more_info def test_add_parser_arguments(self): add = mock.MagicMock() self.auth.add_parser_arguments(add) - self.assertEqual(2, add.call_count) + assert 2 == add.call_count def test_prepare(self): self.auth.prepare() # shouldn't raise any exceptions @@ -77,14 +77,14 @@ class AuthenticatorTest(unittest.TestCase): mock_display.menu.return_value = (display_util.OK, 1,) self.auth.perform([self.achall]) - self.assertTrue(mock_display.menu.called) + assert mock_display.menu.called for call in mock_display.menu.call_args_list: - self.assertIn(self.achall.domain, call[0][0]) - self.assertTrue(all( + assert self.achall.domain in call[0][0] + assert all( webroot in call[0][1] - for webroot in self.config.webroot_map.values())) - self.assertEqual(self.config.webroot_map[self.achall.domain], - self.path) + for webroot in self.config.webroot_map.values()) + assert self.config.webroot_map[self.achall.domain] == \ + self.path @unittest.skipIf(filesystem.POSIX_MODE, reason='Test specific to Windows') @test_util.patch_display_util() @@ -93,9 +93,9 @@ class AuthenticatorTest(unittest.TestCase): mock_display.menu.return_value = (display_util.OK, 1,) self.auth.perform([self.achall]) - self.assertTrue(os.path.exists(os.path.join(self.root_challenge_path, "web.config"))) + assert os.path.exists(os.path.join(self.root_challenge_path, "web.config")) self.auth.cleanup([self.achall]) - self.assertFalse(os.path.exists(os.path.join(self.root_challenge_path, "web.config"))) + assert not os.path.exists(os.path.join(self.root_challenge_path, "web.config")) @unittest.skipIf(filesystem.POSIX_MODE, reason='Test specific to Windows') @test_util.patch_display_util() @@ -113,7 +113,7 @@ class AuthenticatorTest(unittest.TestCase): from certbot import crypto_util webconfig_hash = crypto_util.sha256sum(webconfig_path) from certbot._internal.plugins.webroot import _WEB_CONFIG_SHA256SUMS - self.assertTrue(webconfig_hash not in _WEB_CONFIG_SHA256SUMS) + assert webconfig_hash not in _WEB_CONFIG_SHA256SUMS @unittest.skipIf(filesystem.POSIX_MODE, reason='Test specific to Windows') def test_foreign_webconfig_multiple_domains(self): @@ -138,13 +138,14 @@ class AuthenticatorTest(unittest.TestCase): mock_display = mock_get_utility() mock_display.menu.side_effect = ((display_util.CANCEL, -1),) - self.assertRaises(errors.PluginError, self.auth.perform, [self.achall]) - self.assertTrue(mock_display.menu.called) + with pytest.raises(errors.PluginError): + self.auth.perform([self.achall]) + assert mock_display.menu.called for call in mock_display.menu.call_args_list: - self.assertIn(self.achall.domain, call[0][0]) - self.assertTrue(all( + assert self.achall.domain in call[0][0] + assert all( webroot in call[0][1] - for webroot in self.config.webroot_map.values())) + for webroot in self.config.webroot_map.values()) @test_util.patch_display_util() def test_new_webroot(self, mock_get_utility): @@ -159,7 +160,7 @@ class AuthenticatorTest(unittest.TestCase): self.auth.perform([self.achall]) - self.assertEqual(self.config.webroot_map[self.achall.domain], self.path) + assert self.config.webroot_map[self.achall.domain] == self.path @test_util.patch_display_util() def test_new_webroot_empty_map_cancel(self, mock_get_utility): @@ -170,14 +171,14 @@ class AuthenticatorTest(unittest.TestCase): mock_display.menu.return_value = (display_util.OK, 0,) with mock.patch('certbot.display.ops.validated_directory') as m: m.return_value = (display_util.CANCEL, -1) - self.assertRaises(errors.PluginError, - self.auth.perform, - [self.achall]) + with pytest.raises(errors.PluginError): + self.auth.perform([self.achall]) def test_perform_missing_root(self): self.config.webroot_path = None self.config.webroot_map = {} - self.assertRaises(errors.PluginError, self.auth.perform, []) + with pytest.raises(errors.PluginError): + self.auth.perform([]) def test_perform_reraises_other_errors(self): self.auth.full_path = os.path.join(self.path, "null") @@ -191,7 +192,8 @@ class AuthenticatorTest(unittest.TestCase): print("Warning, running tests as root skips permissions tests...") except IOError: # ok, permissions work, test away... - self.assertRaises(errors.PluginError, self.auth.perform, []) + with pytest.raises(errors.PluginError): + self.auth.perform([]) filesystem.chmod(self.path, 0o700) @mock.patch("certbot._internal.plugins.webroot.filesystem.copy_ownership_and_apply_mode") @@ -212,7 +214,7 @@ class AuthenticatorTest(unittest.TestCase): with mock.patch('certbot.display.ops.validated_directory') as m: m.return_value = (display_util.OK, new_webroot,) self.auth.perform([achall]) - self.assertEqual(self.config.webroot_map[achall.domain], new_webroot) + assert self.config.webroot_map[achall.domain] == new_webroot def test_perform_permissions(self): self.auth.prepare() @@ -220,32 +222,31 @@ class AuthenticatorTest(unittest.TestCase): # Remove exec bit from permission check, so that it # matches the file self.auth.perform([self.achall]) - self.assertTrue(filesystem.check_mode(self.validation_path, 0o644)) + assert filesystem.check_mode(self.validation_path, 0o644) # Check permissions of the directories for dirpath, dirnames, _ in os.walk(self.path): for directory in dirnames: full_path = os.path.join(dirpath, directory) - self.assertTrue(filesystem.check_mode(full_path, 0o755)) + assert filesystem.check_mode(full_path, 0o755) - self.assertTrue(filesystem.has_same_ownership(self.validation_path, self.path)) + assert filesystem.has_same_ownership(self.validation_path, self.path) def test_perform_cleanup(self): self.auth.prepare() responses = self.auth.perform([self.achall]) - self.assertEqual(1, len(responses)) - self.assertTrue(os.path.exists(self.validation_path)) + assert 1 == len(responses) + assert os.path.exists(self.validation_path) with open(self.validation_path) as validation_f: validation = validation_f.read() - self.assertTrue( - challenges.KeyAuthorizationChallengeResponse( + assert challenges.KeyAuthorizationChallengeResponse( key_authorization=validation).verify( - self.achall.chall, KEY.public_key())) + self.achall.chall, KEY.public_key()) self.auth.cleanup([self.achall]) - self.assertFalse(os.path.exists(self.validation_path)) - self.assertFalse(os.path.exists(self.root_challenge_path)) - self.assertFalse(os.path.exists(self.partial_root_challenge_path)) + assert not os.path.exists(self.validation_path) + assert not os.path.exists(self.root_challenge_path) + assert not os.path.exists(self.partial_root_challenge_path) def test_perform_cleanup_existing_dirs(self): filesystem.mkdir(self.partial_root_challenge_path) @@ -254,8 +255,8 @@ class AuthenticatorTest(unittest.TestCase): self.auth.cleanup([self.achall]) # Ensure we don't "clean up" directories that previously existed - self.assertFalse(os.path.exists(self.validation_path)) - self.assertFalse(os.path.exists(self.root_challenge_path)) + assert not os.path.exists(self.validation_path) + assert not os.path.exists(self.root_challenge_path) def test_perform_cleanup_multiple_challenges(self): bingo_achall = achallenges.KeyAuthorizationAnnotatedChallenge( @@ -269,11 +270,11 @@ class AuthenticatorTest(unittest.TestCase): self.auth.perform([bingo_achall, self.achall]) self.auth.cleanup([self.achall]) - self.assertFalse(os.path.exists(bingo_validation_path)) - self.assertTrue(os.path.exists(self.root_challenge_path)) + assert not os.path.exists(bingo_validation_path) + assert os.path.exists(self.root_challenge_path) self.auth.cleanup([bingo_achall]) - self.assertFalse(os.path.exists(self.validation_path)) - self.assertFalse(os.path.exists(self.root_challenge_path)) + assert not os.path.exists(self.validation_path) + assert not os.path.exists(self.root_challenge_path) def test_cleanup_leftovers(self): self.auth.prepare() @@ -283,8 +284,8 @@ class AuthenticatorTest(unittest.TestCase): filesystem.mkdir(leftover_path) self.auth.cleanup([self.achall]) - self.assertFalse(os.path.exists(self.validation_path)) - self.assertTrue(os.path.exists(self.root_challenge_path)) + assert not os.path.exists(self.validation_path) + assert os.path.exists(self.root_challenge_path) os.rmdir(leftover_path) @@ -298,8 +299,8 @@ class AuthenticatorTest(unittest.TestCase): mock_rmdir.side_effect = os_error self.auth.cleanup([self.achall]) - self.assertFalse(os.path.exists(self.validation_path)) - self.assertTrue(os.path.exists(self.root_challenge_path)) + assert not os.path.exists(self.validation_path) + assert os.path.exists(self.root_challenge_path) class WebrootActionTest(unittest.TestCase): @@ -319,27 +320,26 @@ class WebrootActionTest(unittest.TestCase): def test_webroot_map_action(self): args = self.parser.parse_args( ["--webroot-map", json.dumps({'thing.com': self.path})]) - self.assertEqual(args.webroot_map["thing.com"], self.path) + assert args.webroot_map["thing.com"] == self.path def test_domain_before_webroot(self): args = self.parser.parse_args( "-d {0} -w {1}".format(self.achall.domain, self.path).split()) config = self._get_config_after_perform(args) - self.assertEqual(config.webroot_map[self.achall.domain], self.path) + assert config.webroot_map[self.achall.domain] == self.path def test_domain_before_webroot_error(self): - self.assertRaises(errors.PluginError, self.parser.parse_args, - "-d foo -w bar -w baz".split()) - self.assertRaises(errors.PluginError, self.parser.parse_args, - "-d foo -w bar -d baz -w qux".split()) + with pytest.raises(errors.PluginError): + self.parser.parse_args("-d foo -w bar -w baz".split()) + with pytest.raises(errors.PluginError): + self.parser.parse_args("-d foo -w bar -d baz -w qux".split()) def test_multiwebroot(self): args = self.parser.parse_args("-w {0} -d {1} -w {2} -d bar".format( self.path, self.achall.domain, tempfile.mkdtemp()).split()) - self.assertEqual(args.webroot_map[self.achall.domain], self.path) + assert args.webroot_map[self.achall.domain] == self.path config = self._get_config_after_perform(args) - self.assertEqual( - config.webroot_map[self.achall.domain], self.path) + assert config.webroot_map[self.achall.domain] == self.path def test_webroot_map_partial_without_perform(self): # This test acknowledges the fact that webroot_map content will be partial if webroot @@ -351,8 +351,8 @@ class WebrootActionTest(unittest.TestCase): other_webroot_path = tempfile.mkdtemp() args = self.parser.parse_args("-w {0} -d {1} -w {2} -d bar".format( self.path, self.achall.domain, other_webroot_path).split()) - self.assertEqual(args.webroot_map, {self.achall.domain: self.path}) - self.assertEqual(args.webroot_path, [self.path, other_webroot_path]) + assert args.webroot_map == {self.achall.domain: self.path} + assert args.webroot_path == [self.path, other_webroot_path] def _get_config_after_perform(self, config): from certbot._internal.plugins.webroot import Authenticator diff --git a/certbot/tests/renewal_test.py b/certbot/tests/renewal_test.py index 93036fd6c..0bb915345 100644 --- a/certbot/tests/renewal_test.py +++ b/certbot/tests/renewal_test.py @@ -28,7 +28,7 @@ class RenewalTest(test_util.ConfigTestCase): # pylint: disable=protected-access from certbot._internal import renewal renewal._restore_webroot_config(config, renewalparams) - self.assertEqual(config.webroot_path, ['/var/www/']) + assert config.webroot_path == ['/var/www/'] @mock.patch('certbot._internal.renewal.cli.set_by_cli') def test_webroot_params_conservation(self, mock_set_by_cli): @@ -43,16 +43,16 @@ class RenewalTest(test_util.ConfigTestCase): 'webroot_path': ['/var/www/test', '/var/www/other'], } renewal._restore_webroot_config(self.config, renewalparams) # pylint: disable=protected-access - self.assertEqual(self.config.webroot_map, {'test.example.com': '/var/www/test'}) - self.assertEqual(self.config.webroot_path, ['/var/www/test', '/var/www/other']) + assert self.config.webroot_map == {'test.example.com': '/var/www/test'} + assert self.config.webroot_path == ['/var/www/test', '/var/www/other'] renewalparams = { 'webroot_map': {}, 'webroot_path': '/var/www/test', } renewal._restore_webroot_config(self.config, renewalparams) # pylint: disable=protected-access - self.assertEqual(self.config.webroot_map, {}) - self.assertEqual(self.config.webroot_path, ['/var/www/test']) + assert self.config.webroot_map == {} + assert self.config.webroot_path == ['/var/www/test'] @mock.patch('certbot._internal.renewal._avoid_reuse_key_conflicts') def test_reuse_key_renewal_params(self, unused_mock_avoid_reuse_conflicts): @@ -122,9 +122,9 @@ class RenewalTest(test_util.ConfigTestCase): with mock.patch('certbot._internal.renewal.hooks.renew_hook'): renewal.renew_cert(self.config, None, le_client, lineage) - self.assertEqual(self.config.elliptic_curve, 'secp256r1') - self.assertEqual(self.config.key_type, 'ecdsa') - self.assertTrue(self.config.reuse_key) + assert self.config.elliptic_curve == 'secp256r1' + assert self.config.key_type == 'ecdsa' + assert self.config.reuse_key # None is passed as the existing key, i.e. the key is not actually being reused. le_client.obtain_certificate.assert_called_with(mock.ANY, None) @@ -152,7 +152,7 @@ class RenewalTest(test_util.ConfigTestCase): from certbot._internal import renewal - with self.assertRaisesRegex(errors.Error, "Unable to change the --key-type"): + with pytest.raises(errors.Error, match="Unable to change the --key-type"): renewal.renew_cert(self.config, None, le_client, lineage) # ... unless --no-reuse-key is set @@ -175,7 +175,7 @@ class RenewalTest(test_util.ConfigTestCase): renewal_candidate = renewal.reconstitute(lineage_config, rc_path) # This means that manual_public_ip_logging_ok was not modified in the config based on its # value in the renewal conf file - self.assertIsInstance(lineage_config.manual_public_ip_logging_ok, mock.MagicMock) + assert isinstance(lineage_config.manual_public_ip_logging_ok, mock.MagicMock) class RestoreRequiredConfigElementsTest(test_util.ConfigTestCase): @@ -189,14 +189,14 @@ class RestoreRequiredConfigElementsTest(test_util.ConfigTestCase): def test_allow_subset_of_names_success(self, mock_set_by_cli): mock_set_by_cli.return_value = False self._call(self.config, {'allow_subset_of_names': 'True'}) - self.assertIs(self.config.allow_subset_of_names, True) + assert self.config.allow_subset_of_names is True @mock.patch('certbot._internal.renewal.cli.set_by_cli') def test_allow_subset_of_names_failure(self, mock_set_by_cli): mock_set_by_cli.return_value = False renewalparams = {'allow_subset_of_names': 'maybe'} - self.assertRaises( - errors.Error, self._call, self.config, renewalparams) + with pytest.raises(errors.Error): + self._call(self.config, renewalparams) @mock.patch('certbot._internal.renewal.cli.set_by_cli') def test_pref_challs_list(self, mock_set_by_cli): @@ -204,7 +204,7 @@ class RestoreRequiredConfigElementsTest(test_util.ConfigTestCase): renewalparams = {'pref_challs': 'http-01, dns'.split(',')} self._call(self.config, renewalparams) expected = [challenges.HTTP01.typ, challenges.DNS01.typ] - self.assertEqual(self.config.pref_challs, expected) + assert self.config.pref_challs == expected @mock.patch('certbot._internal.renewal.cli.set_by_cli') def test_pref_challs_str(self, mock_set_by_cli): @@ -212,26 +212,27 @@ class RestoreRequiredConfigElementsTest(test_util.ConfigTestCase): renewalparams = {'pref_challs': 'dns'} self._call(self.config, renewalparams) expected = [challenges.DNS01.typ] - self.assertEqual(self.config.pref_challs, expected) + assert self.config.pref_challs == expected @mock.patch('certbot._internal.renewal.cli.set_by_cli') def test_pref_challs_failure(self, mock_set_by_cli): mock_set_by_cli.return_value = False renewalparams = {'pref_challs': 'finding-a-shrubbery'} - self.assertRaises(errors.Error, self._call, self.config, renewalparams) + with pytest.raises(errors.Error): + self._call(self.config, renewalparams) @mock.patch('certbot._internal.renewal.cli.set_by_cli') def test_must_staple_success(self, mock_set_by_cli): mock_set_by_cli.return_value = False self._call(self.config, {'must_staple': 'True'}) - self.assertIs(self.config.must_staple, True) + assert self.config.must_staple is True @mock.patch('certbot._internal.renewal.cli.set_by_cli') def test_must_staple_failure(self, mock_set_by_cli): mock_set_by_cli.return_value = False renewalparams = {'must_staple': 'maybe'} - self.assertRaises( - errors.Error, self._call, self.config, renewalparams) + with pytest.raises(errors.Error): + self._call(self.config, renewalparams) @mock.patch('certbot._internal.renewal.cli.set_by_cli') def test_ancient_server_renewal_conf(self, mock_set_by_cli): @@ -239,7 +240,7 @@ class RestoreRequiredConfigElementsTest(test_util.ConfigTestCase): self.config.server = None mock_set_by_cli.return_value = False self._call(self.config, {'server': constants.V1_URI}) - self.assertEqual(self.config.server, constants.CLI_DEFAULTS['server']) + assert self.config.server == constants.CLI_DEFAULTS['server'] class DescribeResultsTest(unittest.TestCase): diff --git a/certbot/tests/renewupdater_test.py b/certbot/tests/renewupdater_test.py index c2e32f867..eab07cd34 100644 --- a/certbot/tests/renewupdater_test.py +++ b/certbot/tests/renewupdater_test.py @@ -35,60 +35,60 @@ class RenewUpdaterTest(test_util.ConfigTestCase): mock_geti.return_value = mock_generic_updater with mock.patch('certbot._internal.main._init_le_client'): main.renew_cert(self.config, None, mock.MagicMock()) - self.assertTrue(mock_generic_updater.restart.called) + assert mock_generic_updater.restart.called mock_generic_updater.restart.reset_mock() mock_generic_updater.generic_updates.reset_mock() updater.run_generic_updaters(self.config, mock.MagicMock(), None) - self.assertEqual(mock_generic_updater.generic_updates.call_count, 1) - self.assertIs(mock_generic_updater.restart.called, False) + assert mock_generic_updater.generic_updates.call_count == 1 + assert mock_generic_updater.restart.called is False def test_renew_deployer(self): lineage = mock.MagicMock() mock_deployer = self.renew_deployer updater.run_renewal_deployer(self.config, lineage, mock_deployer) - self.assertTrue(mock_deployer.renew_deploy.called_with(lineage)) + assert mock_deployer.renew_deploy.called_with(lineage) @mock.patch("certbot._internal.updater.logger.debug") def test_updater_skip_dry_run(self, mock_log): self.config.dry_run = True updater.run_generic_updaters(self.config, None, None) - self.assertTrue(mock_log.called) - self.assertEqual(mock_log.call_args[0][0], - "Skipping updaters in dry-run mode.") + assert mock_log.called + assert mock_log.call_args[0][0] == \ + "Skipping updaters in dry-run mode." @mock.patch("certbot._internal.updater.logger.debug") def test_deployer_skip_dry_run(self, mock_log): self.config.dry_run = True updater.run_renewal_deployer(self.config, None, None) - self.assertTrue(mock_log.called) - self.assertEqual(mock_log.call_args[0][0], - "Skipping renewal deployer in dry-run mode.") + assert mock_log.called + assert mock_log.call_args[0][0] == \ + "Skipping renewal deployer in dry-run mode." @mock.patch('certbot._internal.plugins.selection.get_unprepared_installer') def test_enhancement_updates(self, mock_geti): mock_geti.return_value = self.mockinstaller updater.run_generic_updaters(self.config, mock.MagicMock(), None) - self.assertTrue(self.mockinstaller.update_autohsts.called) - self.assertEqual(self.mockinstaller.update_autohsts.call_count, 1) + assert self.mockinstaller.update_autohsts.called + assert self.mockinstaller.update_autohsts.call_count == 1 def test_enhancement_deployer(self): updater.run_renewal_deployer(self.config, mock.MagicMock(), self.mockinstaller) - self.assertTrue(self.mockinstaller.deploy_autohsts.called) + assert self.mockinstaller.deploy_autohsts.called @mock.patch('certbot._internal.plugins.selection.get_unprepared_installer') def test_enhancement_updates_not_called(self, mock_geti): self.config.disable_renew_updates = True mock_geti.return_value = self.mockinstaller updater.run_generic_updaters(self.config, mock.MagicMock(), None) - self.assertIs(self.mockinstaller.update_autohsts.called, False) + assert self.mockinstaller.update_autohsts.called is False def test_enhancement_deployer_not_called(self): self.config.disable_renew_updates = True updater.run_renewal_deployer(self.config, mock.MagicMock(), self.mockinstaller) - self.assertIs(self.mockinstaller.deploy_autohsts.called, False) + assert self.mockinstaller.deploy_autohsts.called is False @mock.patch('certbot._internal.plugins.selection.get_unprepared_installer') def test_enhancement_no_updater(self, mock_geti): @@ -104,7 +104,7 @@ class RenewUpdaterTest(test_util.ConfigTestCase): mock_geti.return_value = self.mockinstaller with mock.patch("certbot.plugins.enhancements._INDEX", FAKEINDEX): updater.run_generic_updaters(self.config, mock.MagicMock(), None) - self.assertIs(self.mockinstaller.update_autohsts.called, False) + assert self.mockinstaller.update_autohsts.called is False def test_enhancement_no_deployer(self): FAKEINDEX = [ @@ -119,7 +119,7 @@ class RenewUpdaterTest(test_util.ConfigTestCase): with mock.patch("certbot.plugins.enhancements._INDEX", FAKEINDEX): updater.run_renewal_deployer(self.config, mock.MagicMock(), self.mockinstaller) - self.assertIs(self.mockinstaller.deploy_autohsts.called, False) + assert self.mockinstaller.deploy_autohsts.called is False if __name__ == '__main__': diff --git a/certbot/tests/reverter_test.py b/certbot/tests/reverter_test.py index 7a70a4313..dded4d813 100644 --- a/certbot/tests/reverter_test.py +++ b/certbot/tests/reverter_test.py @@ -47,29 +47,27 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase): no_change = os.path.join(self.reverter.config.backup_dir, path, "CHANGES_SINCE") with open(no_change, "r") as f: x = f.read() - self.assertIn("No changes", x) + assert "No changes" in x 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") self.reverter.add_to_temp_checkpoint(self.sets[1], "save2") - self.assertTrue(os.path.isdir(self.config.temp_checkpoint_dir)) - self.assertEqual(get_save_notes( - self.config.temp_checkpoint_dir), "save1save2") - self.assertFalse(os.path.isfile( - os.path.join(self.config.temp_checkpoint_dir, "NEW_FILES"))) + assert os.path.isdir(self.config.temp_checkpoint_dir) + assert get_save_notes( + self.config.temp_checkpoint_dir) == "save1save2" + assert not os.path.isfile( + os.path.join(self.config.temp_checkpoint_dir, "NEW_FILES")) - self.assertEqual( - get_filepaths(self.config.temp_checkpoint_dir), - "{0}\n{1}\n".format(self.config1, self.config2)) + assert get_filepaths(self.config.temp_checkpoint_dir) == \ + "{0}\n{1}\n".format(self.config1, self.config2) def test_add_to_checkpoint_copy_failure(self): with mock.patch("certbot.reverter.shutil.copy2") as mock_copy2: mock_copy2.side_effect = IOError("bad copy") - self.assertRaises( - errors.ReverterError, self.reverter.add_to_checkpoint, - self.sets[0], "save1") + with pytest.raises(errors.ReverterError): + self.reverter.add_to_checkpoint(self.sets[0], "save1") def test_checkpoint_conflict(self): """Make sure that checkpoint errors are thrown appropriately.""" @@ -81,14 +79,14 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase): # This shouldn't throw an error self.reverter.add_to_temp_checkpoint(self.sets[0], "save2") # Raise error - self.assertRaises(errors.ReverterError, self.reverter.add_to_checkpoint, - self.sets[2], "save3") + with pytest.raises(errors.ReverterError): + self.reverter.add_to_checkpoint(self.sets[2], "save3") # Should not cause an error self.reverter.add_to_checkpoint(self.sets[1], "save4") # Check to make sure new files are also checked... - self.assertRaises(errors.ReverterError, self.reverter.add_to_checkpoint, - {config3}, "invalid save") + with pytest.raises(errors.ReverterError): + self.reverter.add_to_checkpoint({config3}, "invalid save") def test_multiple_saves_and_temp_revert(self): self.reverter.add_to_temp_checkpoint(self.sets[0], "save1") @@ -97,7 +95,7 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase): update_file(self.config1, "new directive change that we won't keep") self.reverter.revert_temporary_config() - self.assertEqual(read_in(self.config1), "directive-dir1") + assert read_in(self.config1) == "directive-dir1" def test_multiple_registration_fail_and_revert(self): @@ -114,10 +112,10 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase): # Simulate Certbot crash... recovery routine is run self.reverter.recovery_routine() - self.assertFalse(os.path.isfile(self.config1)) - self.assertFalse(os.path.isfile(self.config2)) - self.assertFalse(os.path.isfile(config3)) - self.assertFalse(os.path.isfile(config4)) + assert not os.path.isfile(self.config1) + assert not os.path.isfile(self.config2) + assert not os.path.isfile(config3) + assert not os.path.isfile(config4) def test_multiple_registration_same_file(self): self.reverter.register_file_creation(True, self.config1) @@ -127,21 +125,19 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase): files = get_new_files(self.config.temp_checkpoint_dir) - self.assertEqual(len(files), 1) + assert len(files) == 1 def test_register_file_creation_write_error(self): m_open = mock.mock_open() with mock.patch("certbot.reverter.open", m_open, create=True): m_open.side_effect = OSError("bad open") - self.assertRaises( - errors.ReverterError, self.reverter.register_file_creation, - True, self.config1) + with pytest.raises(errors.ReverterError): + self.reverter.register_file_creation(True, self.config1) def test_bad_registration(self): # Made this mistake and want to make sure it doesn't happen again... - self.assertRaises( - errors.ReverterError, self.reverter.register_file_creation, - "filepath") + with pytest.raises(errors.ReverterError): + self.reverter.register_file_creation("filepath") def test_register_undo_command(self): coms = [ @@ -155,15 +151,14 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase): act_coms = get_undo_commands(self.config.temp_checkpoint_dir) for a_com, com in zip(act_coms, coms): - self.assertEqual(a_com, com) + assert a_com == com def test_bad_register_undo_command(self): m_open = mock.mock_open() with mock.patch("certbot.reverter.open", m_open, create=True): m_open.side_effect = OSError("bad open") - self.assertRaises( - errors.ReverterError, self.reverter.register_undo_command, - True, ["command"]) + with pytest.raises(errors.ReverterError): + self.reverter.register_undo_command(True, ["command"]) @mock.patch("certbot.util.run_script") def test_run_undo_commands(self, mock_run): @@ -177,7 +172,7 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase): self.reverter.revert_temporary_config() - self.assertEqual(mock_run.call_count, 2) + assert mock_run.call_count == 2 def test_recovery_routine_in_progress_failure(self): self.reverter.add_to_checkpoint(self.sets[0], "perm save") @@ -185,7 +180,8 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase): # pylint: disable=protected-access self.reverter._recover_checkpoint = mock.MagicMock( side_effect=errors.ReverterError) - self.assertRaises(errors.ReverterError, self.reverter.recovery_routine) + with pytest.raises(errors.ReverterError): + self.reverter.recovery_routine() def test_recover_checkpoint_revert_temp_failures(self): @@ -197,8 +193,8 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase): self.reverter.add_to_temp_checkpoint(self.sets[0], "config1 save") - self.assertRaises( - errors.ReverterError, self.reverter.revert_temporary_config) + with pytest.raises(errors.ReverterError): + self.reverter.revert_temporary_config() def test_recover_checkpoint_rollback_failure(self): mock_recover = mock.MagicMock( @@ -209,38 +205,38 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase): self.reverter.add_to_checkpoint(self.sets[0], "config1 save") self.reverter.finalize_checkpoint("Title") - self.assertRaises( - errors.ReverterError, self.reverter.rollback_checkpoints, 1) + with pytest.raises(errors.ReverterError): + self.reverter.rollback_checkpoints(1) def test_recover_checkpoint_copy_failure(self): self.reverter.add_to_temp_checkpoint(self.sets[0], "save1") with mock.patch("certbot.reverter.shutil.copy2") as mock_copy2: mock_copy2.side_effect = OSError("bad copy") - self.assertRaises( - errors.ReverterError, self.reverter.revert_temporary_config) + with pytest.raises(errors.ReverterError): + self.reverter.revert_temporary_config() def test_recover_checkpoint_rm_failure(self): self.reverter.add_to_temp_checkpoint(self.sets[0], "temp save") with mock.patch("certbot.reverter.shutil.rmtree") as mock_rmtree: mock_rmtree.side_effect = OSError("Cannot remove tree") - self.assertRaises( - errors.ReverterError, self.reverter.revert_temporary_config) + with pytest.raises(errors.ReverterError): + self.reverter.revert_temporary_config() @mock.patch("certbot.reverter.logger.warning") def test_recover_checkpoint_missing_new_files(self, mock_warn): self.reverter.register_file_creation( True, os.path.join(self.dir1, "missing_file.txt")) self.reverter.revert_temporary_config() - self.assertEqual(mock_warn.call_count, 1) + assert mock_warn.call_count == 1 @mock.patch("certbot.reverter.os.remove") def test_recover_checkpoint_remove_failure(self, mock_remove): self.reverter.register_file_creation(True, self.config1) mock_remove.side_effect = OSError("Can't remove") - self.assertRaises( - errors.ReverterError, self.reverter.revert_temporary_config) + with pytest.raises(errors.ReverterError): + self.reverter.revert_temporary_config() def test_recovery_routine_temp_and_perm(self): # Register a new perm checkpoint file @@ -268,12 +264,12 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase): # Now Run tests # These were new files.. they should be removed - self.assertFalse(os.path.isfile(config3)) - self.assertFalse(os.path.isfile(config4)) + assert not os.path.isfile(config3) + assert not os.path.isfile(config4) # Check to make sure everything got rolled back appropriately - self.assertEqual(read_in(self.config1), "directive-dir1") - self.assertEqual(read_in(self.config2), "directive-dir2") + assert read_in(self.config1) == "directive-dir1" + assert read_in(self.config2) == "directive-dir2" class TestFullCheckpointsReverter(test_util.ConfigTestCase): @@ -298,42 +294,41 @@ class TestFullCheckpointsReverter(test_util.ConfigTestCase): logging.disable(logging.NOTSET) def test_rollback_improper_inputs(self): - self.assertRaises( - errors.ReverterError, self.reverter.rollback_checkpoints, "-1") - self.assertRaises( - errors.ReverterError, self.reverter.rollback_checkpoints, -1000) - self.assertRaises( - errors.ReverterError, self.reverter.rollback_checkpoints, "one") + with pytest.raises(errors.ReverterError): + self.reverter.rollback_checkpoints("-1") + with pytest.raises(errors.ReverterError): + self.reverter.rollback_checkpoints(-1000) + with pytest.raises(errors.ReverterError): + self.reverter.rollback_checkpoints("one") def test_rollback_finalize_checkpoint_valid_inputs(self): config3 = self._setup_three_checkpoints() # Check resulting backup directory - self.assertEqual(len(os.listdir(self.config.backup_dir)), 3) + assert len(os.listdir(self.config.backup_dir)) == 3 # Check rollbacks # First rollback self.reverter.rollback_checkpoints(1) - self.assertEqual(read_in(self.config1), "update config1") - self.assertEqual(read_in(self.config2), "update config2") + assert read_in(self.config1) == "update config1" + assert read_in(self.config2) == "update config2" # config3 was not included in checkpoint - self.assertEqual(read_in(config3), "Final form config3") + assert read_in(config3) == "Final form config3" # Second rollback self.reverter.rollback_checkpoints(1) - self.assertEqual(read_in(self.config1), "update config1") - self.assertEqual(read_in(self.config2), "directive-dir2") - self.assertFalse(os.path.isfile(config3)) + assert read_in(self.config1) == "update config1" + assert read_in(self.config2) == "directive-dir2" + assert not os.path.isfile(config3) # One dir left... check title all_dirs = os.listdir(self.config.backup_dir) - self.assertEqual(len(all_dirs), 1) - self.assertIn( - "First Checkpoint", get_save_notes( - os.path.join(self.config.backup_dir, all_dirs[0]))) + assert len(all_dirs) == 1 + assert "First Checkpoint" in get_save_notes( + os.path.join(self.config.backup_dir, all_dirs[0])) # Final rollback self.reverter.rollback_checkpoints(1) - self.assertEqual(read_in(self.config1), "directive-dir1") + assert read_in(self.config1) == "directive-dir1" def test_finalize_checkpoint_no_in_progress(self): # No need to warn for this... just make sure there are no errors. @@ -344,8 +339,8 @@ class TestFullCheckpointsReverter(test_util.ConfigTestCase): self.reverter.add_to_checkpoint(self.sets[0], "perm save") mock_move.side_effect = OSError("cannot move") - self.assertRaises( - errors.ReverterError, self.reverter.finalize_checkpoint, "Title") + with pytest.raises(errors.ReverterError): + self.reverter.finalize_checkpoint("Title") @mock.patch("certbot.reverter.filesystem.replace") def test_finalize_checkpoint_no_rename_directory(self, mock_replace): @@ -353,28 +348,28 @@ class TestFullCheckpointsReverter(test_util.ConfigTestCase): self.reverter.add_to_checkpoint(self.sets[0], "perm save") mock_replace.side_effect = OSError - self.assertRaises( - errors.ReverterError, self.reverter.finalize_checkpoint, "Title") + with pytest.raises(errors.ReverterError): + self.reverter.finalize_checkpoint("Title") @mock.patch("certbot.reverter.logger") def test_rollback_too_many(self, mock_logger): # Test no exist warning... self.reverter.rollback_checkpoints(1) - self.assertEqual(mock_logger.warning.call_count, 1) + assert mock_logger.warning.call_count == 1 # Test Generic warning self._setup_three_checkpoints() mock_logger.warning.call_count = 0 self.reverter.rollback_checkpoints(4) - self.assertEqual(mock_logger.warning.call_count, 1) + assert mock_logger.warning.call_count == 1 def test_multi_rollback(self): config3 = self._setup_three_checkpoints() self.reverter.rollback_checkpoints(3) - self.assertEqual(read_in(self.config1), "directive-dir1") - self.assertEqual(read_in(self.config2), "directive-dir2") - self.assertFalse(os.path.isfile(config3)) + assert read_in(self.config1) == "directive-dir1" + assert read_in(self.config2) == "directive-dir2" + assert not os.path.isfile(config3) def _setup_three_checkpoints(self): """Generate some finalized checkpoints.""" diff --git a/certbot/tests/storage_test.py b/certbot/tests/storage_test.py index 4cad7899d..34ea95246 100644 --- a/certbot/tests/storage_test.py +++ b/certbot/tests/storage_test.py @@ -51,8 +51,7 @@ class RelevantValuesTest(unittest.TestCase): mock_option_was_set.return_value = True self.values["certbot_foo:bar_baz"] = 42 - self.assertEqual( - self._call(self.values.copy()), self.values) + assert self._call(self.values.copy()) == self.values @mock.patch("certbot._internal.cli.option_was_set") def test_option_set(self, mock_option_was_set): @@ -64,7 +63,7 @@ class RelevantValuesTest(unittest.TestCase): expected_relevant_values = self.values.copy() self.values["hello"] = "there" - self.assertEqual(self._call(self.values), expected_relevant_values) + assert self._call(self.values) == expected_relevant_values @mock.patch("certbot._internal.cli.option_was_set") def test_option_unset(self, mock_option_was_set): @@ -73,18 +72,18 @@ class RelevantValuesTest(unittest.TestCase): expected_relevant_values = self.values.copy() self.values["rsa_key_size"] = 2048 - self.assertEqual(self._call(self.values), expected_relevant_values) + assert self._call(self.values) == expected_relevant_values @mock.patch("certbot._internal.cli.set_by_cli") def test_deprecated_item(self, unused_mock_set_by_cli): # deprecated items should never be relevant to store expected_relevant_values = self.values.copy() self.values["manual_public_ip_logging_ok"] = None - self.assertEqual(self._call(self.values), expected_relevant_values) + assert self._call(self.values) == expected_relevant_values self.values["manual_public_ip_logging_ok"] = True - self.assertEqual(self._call(self.values), expected_relevant_values) + assert self._call(self.values) == expected_relevant_values self.values["manual_public_ip_logging_ok"] = False - self.assertEqual(self._call(self.values), expected_relevant_values) + assert self._call(self.values) == expected_relevant_values class BaseRenewableCertTest(test_util.ConfigTestCase): @@ -155,11 +154,10 @@ class RenewableCertTests(BaseRenewableCertTest): """Tests for certbot._internal.storage.""" def test_initialization(self): - self.assertEqual(self.test_rc.lineagename, "example.org") + assert self.test_rc.lineagename == "example.org" for kind in ALL_FOUR: - self.assertEqual( - getattr(self.test_rc, kind), os.path.join( - self.config.config_dir, "live", "example.org", kind + ".pem")) + assert getattr(self.test_rc, kind) == os.path.join( + self.config.config_dir, "live", "example.org", kind + ".pem") def test_renewal_bad_config(self): """Test that the RenewableCert constructor will complain if @@ -170,11 +168,11 @@ class RenewableCertTests(BaseRenewableCertTest): broken = os.path.join(self.config.config_dir, "broken.conf") with open(broken, "w") as f: f.write("[No closing bracket for you!") - self.assertRaises(errors.CertStorageError, storage.RenewableCert, - broken, self.config) + with pytest.raises(errors.CertStorageError): + storage.RenewableCert(broken, self.config) os.unlink(broken) - self.assertRaises(errors.CertStorageError, storage.RenewableCert, - "fun", self.config) + with pytest.raises(errors.CertStorageError): + storage.RenewableCert("fun", self.config) def test_renewal_incomplete_config(self): """Test that the RenewableCert constructor will complain if @@ -187,18 +185,18 @@ class RenewableCertTests(BaseRenewableCertTest): config["fullchain"] = "imaginary_fullchain.pem" config.filename = os.path.join(self.config.config_dir, "imaginary_config.conf") config.write() - self.assertRaises(errors.CertStorageError, storage.RenewableCert, - config.filename, self.config) + with pytest.raises(errors.CertStorageError): + storage.RenewableCert(config.filename, self.config) def test_no_renewal_version(self): from certbot._internal import storage self._write_out_ex_kinds() - self.assertNotIn("version", self.config_file) + assert "version" not in self.config_file with mock.patch("certbot._internal.storage.logger") as mock_logger: storage.RenewableCert(self.config_file.filename, self.config) - self.assertIs(mock_logger.warning.called, False) + assert mock_logger.warning.called is False def test_renewal_newer_version(self): from certbot._internal import storage @@ -209,68 +207,68 @@ class RenewableCertTests(BaseRenewableCertTest): with mock.patch("certbot._internal.storage.logger") as mock_logger: storage.RenewableCert(self.config_file.filename, self.config) - self.assertTrue(mock_logger.info.called) - self.assertIn("version", mock_logger.info.call_args[0][0]) + assert mock_logger.info.called + assert "version" in mock_logger.info.call_args[0][0] def test_consistent(self): # pylint: disable=protected-access oldcert = self.test_rc.cert self.test_rc.cert = "relative/path" # Absolute path for item requirement - self.assertFalse(self.test_rc._consistent()) + assert not self.test_rc._consistent() self.test_rc.cert = oldcert # Items must exist requirement - self.assertFalse(self.test_rc._consistent()) + assert not self.test_rc._consistent() # Items must be symlinks requirements fill_with_sample_data(self.test_rc) - self.assertFalse(self.test_rc._consistent()) + assert not self.test_rc._consistent() unlink_all(self.test_rc) # Items must point to desired place if they are relative for kind in ALL_FOUR: os.symlink(os.path.join("..", kind + "17.pem"), getattr(self.test_rc, kind)) - self.assertFalse(self.test_rc._consistent()) + assert not self.test_rc._consistent() unlink_all(self.test_rc) # Items must point to desired place if they are absolute for kind in ALL_FOUR: os.symlink(os.path.join(self.config.config_dir, kind + "17.pem"), getattr(self.test_rc, kind)) - self.assertFalse(self.test_rc._consistent()) + assert not self.test_rc._consistent() unlink_all(self.test_rc) # Items must point to things that exist for kind in ALL_FOUR: os.symlink(os.path.join("..", "..", "archive", "example.org", kind + "17.pem"), getattr(self.test_rc, kind)) - self.assertFalse(self.test_rc._consistent()) + assert not self.test_rc._consistent() # This version should work fill_with_sample_data(self.test_rc) - self.assertTrue(self.test_rc._consistent()) + assert self.test_rc._consistent() # Items must point to things that follow the naming convention os.unlink(self.test_rc.fullchain) os.symlink(os.path.join("..", "..", "archive", "example.org", "fullchain_17.pem"), self.test_rc.fullchain) with open(self.test_rc.fullchain, "w") as f: f.write("wrongly-named fullchain") - self.assertFalse(self.test_rc._consistent()) + assert not self.test_rc._consistent() def test_current_target(self): # Relative path logic self._write_out_kind("cert", 17) - self.assertTrue(os.path.samefile(self.test_rc.current_target("cert"), + assert os.path.samefile(self.test_rc.current_target("cert"), os.path.join(self.config.config_dir, "archive", "example.org", - "cert17.pem"))) + "cert17.pem")) # Absolute path logic os.unlink(self.test_rc.cert) os.symlink(os.path.join(self.config.config_dir, "archive", "example.org", "cert17.pem"), self.test_rc.cert) with open(self.test_rc.cert, "w") as f: f.write("cert") - self.assertTrue(os.path.samefile(self.test_rc.current_target("cert"), + assert os.path.samefile(self.test_rc.current_target("cert"), os.path.join(self.config.config_dir, "archive", "example.org", - "cert17.pem"))) + "cert17.pem")) def test_current_version(self): for ver in (1, 5, 10, 20): @@ -278,33 +276,33 @@ class RenewableCertTests(BaseRenewableCertTest): os.unlink(self.test_rc.cert) os.symlink(os.path.join("..", "..", "archive", "example.org", "cert10.pem"), self.test_rc.cert) - self.assertEqual(self.test_rc.current_version("cert"), 10) + assert self.test_rc.current_version("cert") == 10 def test_no_current_version(self): - self.assertIsNone(self.test_rc.current_version("cert")) + assert self.test_rc.current_version("cert") is None def test_latest_and_next_versions(self): for ver in range(1, 6): for kind in ALL_FOUR: self._write_out_kind(kind, ver) - self.assertEqual(self.test_rc.latest_common_version(), 5) - self.assertEqual(self.test_rc.next_free_version(), 6) + assert self.test_rc.latest_common_version() == 5 + assert self.test_rc.next_free_version() == 6 # Having one kind of file of a later version doesn't change the # result self._write_out_kind("privkey", 7) - self.assertEqual(self.test_rc.latest_common_version(), 5) + assert self.test_rc.latest_common_version() == 5 # ... although it does change the next free version - self.assertEqual(self.test_rc.next_free_version(), 8) + assert self.test_rc.next_free_version() == 8 # Nor does having three out of four change the result self._write_out_kind("cert", 7) self._write_out_kind("fullchain", 7) - self.assertEqual(self.test_rc.latest_common_version(), 5) + assert self.test_rc.latest_common_version() == 5 # If we have everything from a much later version, it does change # the result for kind in ALL_FOUR: self._write_out_kind(kind, 17) - self.assertEqual(self.test_rc.latest_common_version(), 17) - self.assertEqual(self.test_rc.next_free_version(), 18) + assert self.test_rc.latest_common_version() == 17 + assert self.test_rc.next_free_version() == 18 @mock.patch("certbot._internal.storage.logger") def test_ensure_deployed(self, mock_logger): @@ -313,54 +311,54 @@ class RenewableCertTests(BaseRenewableCertTest): self.test_rc.latest_common_version = mock.Mock() mock_has_pending.return_value = False - self.assertIs(self.test_rc.ensure_deployed(), True) - self.assertEqual(mock_update.call_count, 0) - self.assertEqual(mock_logger.warning.call_count, 0) + assert self.test_rc.ensure_deployed() is True + assert mock_update.call_count == 0 + assert mock_logger.warning.call_count == 0 mock_has_pending.return_value = True - self.assertIs(self.test_rc.ensure_deployed(), False) - self.assertEqual(mock_update.call_count, 1) - self.assertEqual(mock_logger.warning.call_count, 1) + assert self.test_rc.ensure_deployed() is False + assert mock_update.call_count == 1 + assert mock_logger.warning.call_count == 1 def test_update_link_to(self): for ver in range(1, 6): for kind in ALL_FOUR: self._write_out_kind(kind, ver) - self.assertEqual(ver, self.test_rc.current_version(kind)) + assert ver == self.test_rc.current_version(kind) # pylint: disable=protected-access self.test_rc._update_link_to("cert", 3) self.test_rc._update_link_to("privkey", 2) - self.assertEqual(3, self.test_rc.current_version("cert")) - self.assertEqual(2, self.test_rc.current_version("privkey")) - self.assertEqual(5, self.test_rc.current_version("chain")) - self.assertEqual(5, self.test_rc.current_version("fullchain")) + assert 3 == self.test_rc.current_version("cert") + assert 2 == self.test_rc.current_version("privkey") + assert 5 == self.test_rc.current_version("chain") + assert 5 == self.test_rc.current_version("fullchain") # Currently we are allowed to update to a version that doesn't exist self.test_rc._update_link_to("chain", 3000) # However, current_version doesn't allow querying the resulting # version (because it's a broken link). - self.assertEqual(os.path.basename(filesystem.readlink(self.test_rc.chain)), - "chain3000.pem") + assert os.path.basename(filesystem.readlink(self.test_rc.chain)) == \ + "chain3000.pem" def test_version(self): self._write_out_kind("cert", 12) # TODO: We should probably test that the directory is still the # same, but it's tricky because we can get an absolute # path out when we put a relative path in. - self.assertEqual("cert8.pem", - os.path.basename(self.test_rc.version("cert", 8))) + assert "cert8.pem" == \ + os.path.basename(self.test_rc.version("cert", 8)) def test_update_all_links_to_success(self): for ver in range(1, 6): for kind in ALL_FOUR: self._write_out_kind(kind, ver) - self.assertEqual(ver, self.test_rc.current_version(kind)) - self.assertEqual(self.test_rc.latest_common_version(), 5) + assert ver == self.test_rc.current_version(kind) + assert self.test_rc.latest_common_version() == 5 for ver in range(1, 6): self.test_rc.update_all_links_to(ver) for kind in ALL_FOUR: - self.assertEqual(ver, self.test_rc.current_version(kind)) - self.assertEqual(self.test_rc.latest_common_version(), 5) + assert ver == self.test_rc.current_version(kind) + assert self.test_rc.latest_common_version() == 5 def test_update_all_links_to_partial_failure(self): def unlink_or_raise(path, real_unlink=os.unlink): @@ -373,10 +371,11 @@ class RenewableCertTests(BaseRenewableCertTest): self._write_out_ex_kinds() with mock.patch("certbot._internal.storage.os.unlink") as mock_unlink: mock_unlink.side_effect = unlink_or_raise - self.assertRaises(ValueError, self.test_rc.update_all_links_to, 12) + with pytest.raises(ValueError): + self.test_rc.update_all_links_to(12) for kind in ALL_FOUR: - self.assertEqual(self.test_rc.current_version(kind), 12) + assert self.test_rc.current_version(kind) == 12 def test_update_all_links_to_full_failure(self): def unlink_or_raise(path, real_unlink=os.unlink): @@ -388,35 +387,37 @@ class RenewableCertTests(BaseRenewableCertTest): self._write_out_ex_kinds() with mock.patch("certbot._internal.storage.os.unlink") as mock_unlink: mock_unlink.side_effect = unlink_or_raise - self.assertRaises(ValueError, self.test_rc.update_all_links_to, 12) + with pytest.raises(ValueError): + self.test_rc.update_all_links_to(12) for kind in ALL_FOUR: - self.assertEqual(self.test_rc.current_version(kind), 11) + assert self.test_rc.current_version(kind) == 11 def test_has_pending_deployment(self): for ver in range(1, 6): for kind in ALL_FOUR: self._write_out_kind(kind, ver) - self.assertEqual(ver, self.test_rc.current_version(kind)) + assert ver == self.test_rc.current_version(kind) for ver in range(1, 6): self.test_rc.update_all_links_to(ver) for kind in ALL_FOUR: - self.assertEqual(ver, self.test_rc.current_version(kind)) + assert ver == self.test_rc.current_version(kind) if ver < 5: - self.assertTrue(self.test_rc.has_pending_deployment()) + assert self.test_rc.has_pending_deployment() else: - self.assertFalse(self.test_rc.has_pending_deployment()) + assert not self.test_rc.has_pending_deployment() def test_names(self): # Trying the current version self._write_out_kind("cert", 12, test_util.load_vector("cert-san_512.pem")) - self.assertEqual(self.test_rc.names(), - ["example.com", "www.example.com"]) + assert self.test_rc.names() == \ + ["example.com", "www.example.com"] # Trying missing cert os.unlink(self.test_rc.cert) - self.assertRaises(errors.CertStorageError, self.test_rc.names) + with pytest.raises(errors.CertStorageError): + self.test_rc.names() @mock.patch("certbot._internal.storage.cli") @mock.patch("certbot._internal.storage.datetime") @@ -461,16 +462,16 @@ class RenewableCertTests(BaseRenewableCertTest): sometime = datetime.datetime.utcfromtimestamp(current_time) mock_datetime.datetime.utcnow.return_value = sometime self.test_rc.configuration["renew_before_expiry"] = interval - self.assertEqual(self.test_rc.should_autorenew(), result) + assert self.test_rc.should_autorenew() == result def test_autorenewal_is_enabled(self): self.test_rc.configuration["renewalparams"] = {} - self.assertTrue(self.test_rc.autorenewal_is_enabled()) + assert self.test_rc.autorenewal_is_enabled() self.test_rc.configuration["renewalparams"]["autorenew"] = "True" - self.assertTrue(self.test_rc.autorenewal_is_enabled()) + assert self.test_rc.autorenewal_is_enabled() self.test_rc.configuration["renewalparams"]["autorenew"] = "False" - self.assertFalse(self.test_rc.autorenewal_is_enabled()) + assert not self.test_rc.autorenewal_is_enabled() @mock.patch("certbot._internal.storage.cli") @mock.patch("certbot._internal.storage.RenewableCert.ocsp_revoked") @@ -480,13 +481,13 @@ class RenewableCertTests(BaseRenewableCertTest): mock_cli.set_by_cli.return_value = False # Autorenewal turned off self.test_rc.configuration["renewalparams"] = {"autorenew": "False"} - self.assertFalse(self.test_rc.should_autorenew()) + assert not self.test_rc.should_autorenew() self.test_rc.configuration["renewalparams"]["autorenew"] = "True" for kind in ALL_FOUR: self._write_out_kind(kind, 12) # Mandatory renewal on the basis of OCSP revocation mock_ocsp.return_value = True - self.assertTrue(self.test_rc.should_autorenew()) + assert self.test_rc.should_autorenew() mock_ocsp.return_value = False @mock.patch("certbot._internal.storage.relevant_values") @@ -499,58 +500,53 @@ class RenewableCertTests(BaseRenewableCertTest): for kind in ALL_FOUR: self._write_out_kind(kind, ver) self.test_rc.update_all_links_to(3) - self.assertEqual( - 6, self.test_rc.save_successor(3, b'new cert', None, - b'new chain', self.config)) + assert 6 == self.test_rc.save_successor(3, b'new cert', None, + b'new chain', self.config) with open(self.test_rc.version("cert", 6)) as f: - self.assertEqual(f.read(), "new cert") + assert f.read() == "new cert" with open(self.test_rc.version("chain", 6)) as f: - self.assertEqual(f.read(), "new chain") + assert f.read() == "new chain" with open(self.test_rc.version("fullchain", 6)) as f: - self.assertEqual(f.read(), "new cert" + "new chain") + assert f.read() == "new cert" + "new chain" # version 6 of the key should be a link back to version 3 - self.assertFalse(os.path.islink(self.test_rc.version("privkey", 3))) - self.assertTrue(os.path.islink(self.test_rc.version("privkey", 6))) + assert not os.path.islink(self.test_rc.version("privkey", 3)) + assert os.path.islink(self.test_rc.version("privkey", 6)) # Let's try two more updates - self.assertEqual( - 7, self.test_rc.save_successor(6, b'again', None, - b'newer chain', self.config)) - self.assertEqual( - 8, self.test_rc.save_successor(7, b'hello', None, - b'other chain', self.config)) + assert 7 == self.test_rc.save_successor(6, b'again', None, + b'newer chain', self.config) + assert 8 == self.test_rc.save_successor(7, b'hello', None, + b'other chain', self.config) # All of the subsequent versions should link directly to the original # privkey. for i in (6, 7, 8): - self.assertTrue(os.path.islink(self.test_rc.version("privkey", i))) - self.assertEqual("privkey3.pem", os.path.basename(filesystem.readlink( - self.test_rc.version("privkey", i)))) + assert os.path.islink(self.test_rc.version("privkey", i)) + assert "privkey3.pem" == os.path.basename(filesystem.readlink( + self.test_rc.version("privkey", i))) for kind in ALL_FOUR: - self.assertEqual(self.test_rc.available_versions(kind), list(range(1, 9))) - self.assertEqual(self.test_rc.current_version(kind), 3) + assert self.test_rc.available_versions(kind) == list(range(1, 9)) + assert self.test_rc.current_version(kind) == 3 # Test updating from latest version rather than old version self.test_rc.update_all_links_to(8) - self.assertEqual( - 9, self.test_rc.save_successor(8, b'last', None, - b'attempt', self.config)) + assert 9 == self.test_rc.save_successor(8, b'last', None, + b'attempt', self.config) for kind in ALL_FOUR: - self.assertEqual(self.test_rc.available_versions(kind), - list(range(1, 10))) - self.assertEqual(self.test_rc.current_version(kind), 8) + assert self.test_rc.available_versions(kind) == \ + list(range(1, 10)) + assert self.test_rc.current_version(kind) == 8 with open(self.test_rc.version("fullchain", 9)) as f: - self.assertEqual(f.read(), "last" + "attempt") + assert f.read() == "last" + "attempt" temp_config_file = os.path.join(self.config.renewal_configs_dir, self.test_rc.lineagename) + ".conf.new" with open(temp_config_file, "w") as f: f.write("We previously crashed while writing me :(") # Test updating when providing a new privkey. The key should # be saved in a new file rather than creating a new symlink. - self.assertEqual( - 10, self.test_rc.save_successor(9, b'with', b'a', - b'key', self.config)) - self.assertTrue(os.path.exists(self.test_rc.version("privkey", 10))) - self.assertFalse(os.path.islink(self.test_rc.version("privkey", 10))) - self.assertFalse(os.path.exists(temp_config_file)) + assert 10 == self.test_rc.save_successor(9, b'with', b'a', + b'key', self.config) + assert os.path.exists(self.test_rc.version("privkey", 10)) + assert not os.path.islink(self.test_rc.version("privkey", 10)) + assert not os.path.exists(temp_config_file) @test_util.skip_on_windows('Group/everybody permissions are not maintained on Windows.') @mock.patch("certbot._internal.storage.relevant_values") @@ -561,18 +557,18 @@ class RenewableCertTests(BaseRenewableCertTest): for kind in ALL_FOUR: self._write_out_kind(kind, 1) self.test_rc.update_all_links_to(1) - self.assertTrue(filesystem.check_mode(self.test_rc.version("privkey", 1), 0o600)) + assert filesystem.check_mode(self.test_rc.version("privkey", 1), 0o600) filesystem.chmod(self.test_rc.version("privkey", 1), 0o444) # If no new key, permissions should be the same (we didn't write any keys) self.test_rc.save_successor(1, b"newcert", None, b"new chain", self.config) - self.assertTrue(filesystem.check_mode(self.test_rc.version("privkey", 2), 0o444)) + assert filesystem.check_mode(self.test_rc.version("privkey", 2), 0o444) # If new key, permissions should be kept as 644 self.test_rc.save_successor(2, b"newcert", b"new_privkey", b"new chain", self.config) - self.assertTrue(filesystem.check_mode(self.test_rc.version("privkey", 3), 0o644)) + assert filesystem.check_mode(self.test_rc.version("privkey", 3), 0o644) # If permissions reverted, next renewal will also revert permissions of new key filesystem.chmod(self.test_rc.version("privkey", 3), 0o400) self.test_rc.save_successor(3, b"newcert", b"new_privkey", b"new chain", self.config) - self.assertTrue(filesystem.check_mode(self.test_rc.version("privkey", 4), 0o600)) + assert filesystem.check_mode(self.test_rc.version("privkey", 4), 0o600) @mock.patch("certbot._internal.storage.relevant_values") @mock.patch("certbot._internal.storage.filesystem.copy_ownership_and_apply_mode") @@ -584,9 +580,9 @@ class RenewableCertTests(BaseRenewableCertTest): self._write_out_kind(kind, 1) self.test_rc.update_all_links_to(1) self.test_rc.save_successor(1, b"newcert", None, b"new chain", self.config) - self.assertIs(mock_ownership.called, False) + assert mock_ownership.called is False self.test_rc.save_successor(2, b"newcert", b"new_privkey", b"new chain", self.config) - self.assertTrue(mock_ownership.called) + assert mock_ownership.called @mock.patch("certbot._internal.storage.relevant_values") def test_new_lineage(self, mock_rv): @@ -601,41 +597,40 @@ class RenewableCertTests(BaseRenewableCertTest): # This consistency check tests most relevant properties about the # newly created cert lineage. # pylint: disable=protected-access - 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"))) - self.assertTrue(filesystem.check_mode(result.key_path, 0o600)) + assert result._consistent() + assert os.path.exists(os.path.join( + self.config.renewal_configs_dir, "the-lineage.com.conf")) + assert os.path.exists(os.path.join( + self.config.live_dir, "README")) + assert os.path.exists(os.path.join( + self.config.live_dir, "the-lineage.com", "README")) + assert filesystem.check_mode(result.key_path, 0o600) with open(result.fullchain, "rb") as f: - self.assertEqual(f.read(), b"cert" + b"chain") + assert f.read() == b"cert" + b"chain" # Let's do it again and make sure it makes a different lineage result = storage.RenewableCert.new_lineage( "the-lineage.com", b"cert2", b"privkey2", b"chain2", self.config) - self.assertTrue(os.path.exists(os.path.join( - self.config.renewal_configs_dir, "the-lineage.com-0001.conf"))) - self.assertTrue(os.path.exists(os.path.join( - self.config.live_dir, "the-lineage.com-0001", "README"))) + assert os.path.exists(os.path.join( + self.config.renewal_configs_dir, "the-lineage.com-0001.conf")) + assert os.path.exists(os.path.join( + self.config.live_dir, "the-lineage.com-0001", "README")) # Allow write to existing but empty dir filesystem.mkdir(os.path.join(self.config.default_archive_dir, "the-lineage.com-0002")) result = storage.RenewableCert.new_lineage( "the-lineage.com", b"cert3", b"privkey3", b"chain3", self.config) - self.assertTrue(os.path.exists(os.path.join( - self.config.live_dir, "the-lineage.com-0002", "README"))) - self.assertTrue(filesystem.check_mode(result.key_path, 0o600)) + assert os.path.exists(os.path.join( + self.config.live_dir, "the-lineage.com-0002", "README")) + assert filesystem.check_mode(result.key_path, 0o600) # Now trigger the detection of already existing files shutil.copytree(os.path.join(self.config.live_dir, "the-lineage.com"), os.path.join(self.config.live_dir, "the-lineage.com-0003")) - self.assertRaises(errors.CertStorageError, - storage.RenewableCert.new_lineage, "the-lineage.com", + with pytest.raises(errors.CertStorageError): + storage.RenewableCert.new_lineage("the-lineage.com", b"cert4", b"privkey4", b"chain4", self.config) shutil.copytree(os.path.join(self.config.live_dir, "the-lineage.com"), os.path.join(self.config.live_dir, "other-example.com")) - self.assertRaises(errors.CertStorageError, - storage.RenewableCert.new_lineage, - "other-example.com", b"cert5", + with pytest.raises(errors.CertStorageError): + storage.RenewableCert.new_lineage("other-example.com", b"cert5", b"privkey5", b"chain5", self.config) # Make sure it can accept renewal parameters result = storage.RenewableCert.new_lineage( @@ -657,39 +652,36 @@ class RenewableCertTests(BaseRenewableCertTest): storage.RenewableCert.new_lineage( "the-lineage.com", b"cert2", b"privkey2", b"chain2", self.config) - self.assertTrue(os.path.exists( + assert 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, "the-lineage.com", "privkey.pem"))) - self.assertTrue(os.path.exists(os.path.join( - self.config.default_archive_dir, "the-lineage.com", "privkey1.pem"))) + self.config.renewal_configs_dir, "the-lineage.com.conf")) + assert os.path.exists(os.path.join( + self.config.live_dir, "the-lineage.com", "privkey.pem")) + assert os.path.exists(os.path.join( + self.config.default_archive_dir, "the-lineage.com", "privkey1.pem")) @mock.patch("certbot._internal.storage.util.unique_lineage_name") def test_invalid_config_filename(self, mock_uln): from certbot._internal import storage mock_uln.return_value = "this_does_not_end_with_dot_conf", "yikes" - self.assertRaises(errors.CertStorageError, - storage.RenewableCert.new_lineage, "example.com", + with pytest.raises(errors.CertStorageError): + storage.RenewableCert.new_lineage("example.com", "cert", "privkey", "chain", self.config) def test_bad_kind(self): - self.assertRaises( - errors.CertStorageError, self.test_rc.current_target, "elephant") - self.assertRaises( - errors.CertStorageError, self.test_rc.current_version, "elephant") - self.assertRaises( - errors.CertStorageError, self.test_rc.version, "elephant", 17) - self.assertRaises( - errors.CertStorageError, - self.test_rc.available_versions, "elephant") - self.assertRaises( - errors.CertStorageError, - self.test_rc.newest_available_version, "elephant") + with pytest.raises(errors.CertStorageError): + self.test_rc.current_target("elephant") + with pytest.raises(errors.CertStorageError): + self.test_rc.current_version("elephant") + with pytest.raises(errors.CertStorageError): + self.test_rc.version("elephant", 17) + with pytest.raises(errors.CertStorageError): + self.test_rc.available_versions("elephant") + with pytest.raises(errors.CertStorageError): + self.test_rc.newest_available_version("elephant") # pylint: disable=protected-access - self.assertRaises( - errors.CertStorageError, - self.test_rc._update_link_to, "elephant", 17) + with pytest.raises(errors.CertStorageError): + self.test_rc._update_link_to("elephant", 17) @mock.patch("certbot.ocsp.RevocationChecker.ocsp_revoked_by_paths") def test_ocsp_revoked(self, mock_checker): @@ -702,24 +694,24 @@ class RenewableCertTests(BaseRenewableCertTest): # Test with cert revoked mock_checker.return_value = True - self.assertTrue(self.test_rc.ocsp_revoked(version)) - self.assertEqual(mock_checker.call_args[0][0], expected_cert_path) - self.assertEqual(mock_checker.call_args[0][1], expected_chain_path) + assert self.test_rc.ocsp_revoked(version) + assert mock_checker.call_args[0][0] == expected_cert_path + assert mock_checker.call_args[0][1] == expected_chain_path # Test with cert not revoked mock_checker.return_value = False - self.assertFalse(self.test_rc.ocsp_revoked(version)) - self.assertEqual(mock_checker.call_args[0][0], expected_cert_path) - self.assertEqual(mock_checker.call_args[0][1], expected_chain_path) + assert not self.test_rc.ocsp_revoked(version) + assert mock_checker.call_args[0][0] == expected_cert_path + assert mock_checker.call_args[0][1] == expected_chain_path # Test with error mock_checker.side_effect = ValueError with mock.patch("certbot._internal.storage.logger.warning") as logger: - self.assertFalse(self.test_rc.ocsp_revoked(version)) - self.assertEqual(mock_checker.call_args[0][0], expected_cert_path) - self.assertEqual(mock_checker.call_args[0][1], expected_chain_path) + assert not self.test_rc.ocsp_revoked(version) + assert mock_checker.call_args[0][0] == expected_cert_path + assert mock_checker.call_args[0][1] == expected_chain_path log_msg = logger.call_args[0][0] - self.assertIn("An error occurred determining the OCSP status", log_msg) + assert "An error occurred determining the OCSP status" in log_msg def test_add_time_interval(self): from certbot._internal import storage @@ -760,38 +752,36 @@ class RenewableCertTests(BaseRenewableCertTest): for parameters, excepted in intended.items(): base_time, interval = parameters - self.assertEqual(storage.add_time_interval(base_time, interval), - excepted) + assert storage.add_time_interval(base_time, interval) == \ + excepted def test_server(self): self.test_rc.configuration["renewalparams"] = {} - self.assertIsNone(self.test_rc.server) + assert self.test_rc.server is None rp = self.test_rc.configuration["renewalparams"] rp["server"] = "https://acme.example/dir" - self.assertEqual(self.test_rc.server, "https://acme.example/dir") + assert self.test_rc.server == "https://acme.example/dir" def test_is_test_cert(self): self.test_rc.configuration["renewalparams"] = {} rp = self.test_rc.configuration["renewalparams"] - self.assertIs(self.test_rc.is_test_cert, False) + assert self.test_rc.is_test_cert is False rp["server"] = "https://acme-staging-v02.api.letsencrypt.org/directory" - self.assertIs(self.test_rc.is_test_cert, True) + assert self.test_rc.is_test_cert is True rp["server"] = "https://staging.someotherca.com/directory" - self.assertIs(self.test_rc.is_test_cert, True) + assert self.test_rc.is_test_cert is True rp["server"] = "https://acme-v01.api.letsencrypt.org/directory" - self.assertIs(self.test_rc.is_test_cert, False) + assert self.test_rc.is_test_cert is False rp["server"] = "https://acme-v02.api.letsencrypt.org/directory" - self.assertIs(self.test_rc.is_test_cert, False) + assert self.test_rc.is_test_cert is False def test_missing_cert(self): from certbot._internal import storage - self.assertRaises(errors.CertStorageError, - storage.RenewableCert, - self.config_file.filename, self.config) + with pytest.raises(errors.CertStorageError): + storage.RenewableCert(self.config_file.filename, self.config) os.symlink("missing", self.config_file[ALL_FOUR[0]]) - self.assertRaises(errors.CertStorageError, - storage.RenewableCert, - self.config_file.filename, self.config) + with pytest.raises(errors.CertStorageError): + storage.RenewableCert(self.config_file.filename, self.config) def test_write_renewal_config(self): # Mostly tested by the process of creating and updating lineages, @@ -815,16 +805,16 @@ class RenewableCertTests(BaseRenewableCertTest): with open(temp2, "r") as f: content = f.read() # useful value was updated - self.assertIn("useful = new_value", content) + assert "useful = new_value" in content # associated comment was preserved - self.assertIn("A useful value", content) + assert "A useful value" in content # useless value was deleted - self.assertNotIn("useless", content) + assert "useless" not in content # check version was stored - self.assertIn("version = {0}".format(certbot.__version__), content) + assert "version = {0}".format(certbot.__version__) in content # ensure permissions are copied - self.assertEqual(stat.S_IMODE(os.lstat(temp).st_mode), - stat.S_IMODE(os.lstat(temp2).st_mode)) + assert stat.S_IMODE(os.lstat(temp).st_mode) == \ + stat.S_IMODE(os.lstat(temp2).st_mode) def test_update_symlinks(self): from certbot._internal import storage @@ -835,8 +825,8 @@ class RenewableCertTests(BaseRenewableCertTest): archive_path = os.path.join(archive_dir_path, basename) open(archive_path, 'a').close() os.symlink(os.path.join(self.config.config_dir, basename), live_path) - self.assertRaises(errors.CertStorageError, - storage.RenewableCert, self.config_file.filename, + with pytest.raises(errors.CertStorageError): + storage.RenewableCert(self.config_file.filename, self.config) storage.RenewableCert(self.config_file.filename, self.config, update_symlinks=True) @@ -855,8 +845,8 @@ class RenewableCertTests(BaseRenewableCertTest): self._write_out_kind(kind, i) with mock.patch('certbot.compat.os.unlink') as mock_unlink: self.test_rc.truncate() - self.assertEqual(mock_unlink.call_count, 1 * len(ALL_FOUR)) - self.assertIn("1.pem", mock_unlink.call_args_list[0][0][0]) + assert mock_unlink.call_count == 1 * len(ALL_FOUR) + assert "1.pem" in mock_unlink.call_args_list[0][0][0] class DeleteFilesTest(BaseRenewableCertTest): """Tests for certbot._internal.storage.delete_files""" @@ -869,12 +859,12 @@ class DeleteFilesTest(BaseRenewableCertTest): with open(kind_path, 'a'): pass self.config_file.write() - self.assertTrue(os.path.exists(os.path.join( - self.config.renewal_configs_dir, "example.org.conf"))) - self.assertTrue(os.path.exists(os.path.join( - self.config.live_dir, "example.org"))) - self.assertTrue(os.path.exists(os.path.join( - self.config.config_dir, "archive", "example.org"))) + assert os.path.exists(os.path.join( + self.config.renewal_configs_dir, "example.org.conf")) + assert os.path.exists(os.path.join( + self.config.live_dir, "example.org")) + assert os.path.exists(os.path.join( + self.config.config_dir, "archive", "example.org")) def _call(self): from certbot._internal import storage @@ -884,69 +874,71 @@ class DeleteFilesTest(BaseRenewableCertTest): def test_delete_all_files(self): self._call() - self.assertFalse(os.path.exists(os.path.join( - self.config.renewal_configs_dir, "example.org.conf"))) - self.assertFalse(os.path.exists(os.path.join( - self.config.live_dir, "example.org"))) - self.assertFalse(os.path.exists(os.path.join( - self.config.config_dir, "archive", "example.org"))) + assert not os.path.exists(os.path.join( + self.config.renewal_configs_dir, "example.org.conf")) + assert not os.path.exists(os.path.join( + self.config.live_dir, "example.org")) + assert not os.path.exists(os.path.join( + self.config.config_dir, "archive", "example.org")) def test_bad_renewal_config(self): with open(self.config_file.filename, 'a') as config_file: config_file.write("asdfasfasdfasdf") - self.assertRaises(errors.CertStorageError, self._call) - self.assertTrue(os.path.exists(os.path.join( - self.config.live_dir, "example.org"))) - self.assertFalse(os.path.exists(os.path.join( - self.config.renewal_configs_dir, "example.org.conf"))) + with pytest.raises(errors.CertStorageError): + self._call() + assert os.path.exists(os.path.join( + self.config.live_dir, "example.org")) + assert not os.path.exists(os.path.join( + self.config.renewal_configs_dir, "example.org.conf")) def test_no_renewal_config(self): os.remove(self.config_file.filename) - self.assertRaises(errors.CertStorageError, self._call) - self.assertTrue(os.path.exists(os.path.join( - self.config.live_dir, "example.org"))) - self.assertFalse(os.path.exists(self.config_file.filename)) + with pytest.raises(errors.CertStorageError): + self._call() + assert os.path.exists(os.path.join( + self.config.live_dir, "example.org")) + assert not os.path.exists(self.config_file.filename) def test_no_cert_file(self): os.remove(os.path.join( self.config.live_dir, "example.org", "cert.pem")) self._call() - self.assertFalse(os.path.exists(self.config_file.filename)) - self.assertFalse(os.path.exists(os.path.join( - self.config.live_dir, "example.org"))) - self.assertFalse(os.path.exists(os.path.join( - self.config.config_dir, "archive", "example.org"))) + assert not os.path.exists(self.config_file.filename) + assert not os.path.exists(os.path.join( + self.config.live_dir, "example.org")) + assert not os.path.exists(os.path.join( + self.config.config_dir, "archive", "example.org")) def test_no_readme_file(self): os.remove(os.path.join( self.config.live_dir, "example.org", "README")) self._call() - self.assertFalse(os.path.exists(self.config_file.filename)) - self.assertFalse(os.path.exists(os.path.join( - self.config.live_dir, "example.org"))) - self.assertFalse(os.path.exists(os.path.join( - self.config.config_dir, "archive", "example.org"))) + assert not os.path.exists(self.config_file.filename) + assert not os.path.exists(os.path.join( + self.config.live_dir, "example.org")) + assert not os.path.exists(os.path.join( + self.config.config_dir, "archive", "example.org")) def test_livedir_not_empty(self): with open(os.path.join( self.config.live_dir, "example.org", "other_file"), 'a'): pass self._call() - self.assertFalse(os.path.exists(self.config_file.filename)) - self.assertTrue(os.path.exists(os.path.join( - self.config.live_dir, "example.org"))) - self.assertFalse(os.path.exists(os.path.join( - self.config.config_dir, "archive", "example.org"))) + assert not os.path.exists(self.config_file.filename) + assert os.path.exists(os.path.join( + self.config.live_dir, "example.org")) + assert not os.path.exists(os.path.join( + self.config.config_dir, "archive", "example.org")) def test_no_archive(self): archive_dir = os.path.join(self.config.config_dir, "archive", "example.org") os.rmdir(archive_dir) self._call() - self.assertFalse(os.path.exists(self.config_file.filename)) - self.assertFalse(os.path.exists(os.path.join( - self.config.live_dir, "example.org"))) - self.assertFalse(os.path.exists(archive_dir)) + assert not os.path.exists(self.config_file.filename) + assert not os.path.exists(os.path.join( + self.config.live_dir, "example.org")) + assert not os.path.exists(archive_dir) class CertPathForCertNameTest(BaseRenewableCertTest): """Test for certbot._internal.storage.cert_path_for_cert_name""" @@ -963,10 +955,11 @@ class CertPathForCertNameTest(BaseRenewableCertTest): return cert_path_for_cert_name(cli_config, certname) def test_simple_cert_name(self): - self.assertEqual(self._call(self.config, 'example.org'), self.fullchain) + assert self._call(self.config, 'example.org') == self.fullchain def test_no_such_cert_name(self): - self.assertRaises(errors.CertStorageError, self._call, self.config, 'fake-example.org') + with pytest.raises(errors.CertStorageError): + self._call(self.config, 'fake-example.org') if __name__ == "__main__": sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot/tests/util_test.py b/certbot/tests/util_test.py index e02638037..9377ed6b7 100644 --- a/certbot/tests/util_test.py +++ b/certbot/tests/util_test.py @@ -29,7 +29,7 @@ class EnvNoSnapForExternalCallsTest(unittest.TestCase): env_copy_dict['SNAP'] = 'RANDOM_NONSENSE_GARBAGE' env_copy_dict['CERTBOT_SNAPPED'] = 'True' with mock.patch('certbot.compat.os.environ.copy', return_value=env_copy_dict): - self.assertEqual(self._call()['PATH'], original_path) + assert self._call()['PATH'] == original_path def test_noop(self): env_copy_dict_unmodified = os.environ.copy() @@ -40,13 +40,13 @@ class EnvNoSnapForExternalCallsTest(unittest.TestCase): # contains neither necessary key env_copy_dict.pop('SNAP', None) env_copy_dict.pop('CERTBOT_SNAPPED', None) - self.assertEqual(self._call()['PATH'], env_copy_dict_unmodified['PATH']) + assert self._call()['PATH'] == env_copy_dict_unmodified['PATH'] # contains only one necessary key env_copy_dict['SNAP'] = 'RANDOM_NONSENSE_GARBAGE' - self.assertEqual(self._call()['PATH'], env_copy_dict_unmodified['PATH']) + assert self._call()['PATH'] == env_copy_dict_unmodified['PATH'] del env_copy_dict['SNAP'] env_copy_dict['CERTBOT_SNAPPED'] = 'True' - self.assertEqual(self._call()['PATH'], env_copy_dict_unmodified['PATH']) + assert self._call()['PATH'] == env_copy_dict_unmodified['PATH'] class RunScriptTest(unittest.TestCase): @@ -64,20 +64,22 @@ class RunScriptTest(unittest.TestCase): mock_run().stderr = "stderr" out, err = self._call(["test"]) - self.assertEqual(out, "stdout") - self.assertEqual(err, "stderr") + assert out == "stdout" + assert err == "stderr" @mock.patch("certbot.util.subprocess.run") def test_bad_process(self, mock_run): mock_run.side_effect = OSError - self.assertRaises(errors.SubprocessError, self._call, ["test"]) + with pytest.raises(errors.SubprocessError): + self._call(["test"]) @mock.patch("certbot.util.subprocess.run") def test_failure(self, mock_run): mock_run().returncode = 1 - self.assertRaises(errors.SubprocessError, self._call, ["test"]) + with pytest.raises(errors.SubprocessError): + self._call(["test"]) class ExeExistsTest(unittest.TestCase): @@ -90,11 +92,11 @@ class ExeExistsTest(unittest.TestCase): def test_exe_exists(self): with mock.patch("certbot.util.filesystem.is_executable", return_value=True): - self.assertTrue(self._call("/path/to/exe")) + assert self._call("/path/to/exe") def test_exe_not_exists(self): with mock.patch("certbot.util.filesystem.is_executable", return_value=False): - self.assertFalse(self._call("/path/to/exe")) + assert not self._call("/path/to/exe") class LockDirUntilExit(test_util.TempDirTestCase): @@ -119,18 +121,18 @@ class LockDirUntilExit(test_util.TempDirTestCase): self._call(subdir) self._call(subdir) - self.assertEqual(mock_register.call_count, 1) + assert mock_register.call_count == 1 registered_func = mock_register.call_args[0][0] from certbot import util # Despite lock_dir_until_exit has been called twice to subdir, its lock should have been # added only once. So we expect to have two lock references: for self.tempdir and subdir - self.assertEqual(len(util._LOCKS), 2) # pylint: disable=protected-access + assert len(util._LOCKS) == 2 # pylint: disable=protected-access registered_func() # Exception should not be raised # Logically, logger.debug, that would be invoked in case of unlock failure, # should never been called. - self.assertEqual(mock_logger.debug.call_count, 0) + assert mock_logger.debug.call_count == 0 class SetUpCoreDirTest(test_util.TempDirTestCase): @@ -144,13 +146,14 @@ class SetUpCoreDirTest(test_util.TempDirTestCase): def test_success(self, mock_lock): new_dir = os.path.join(self.tempdir, 'new') self._call(new_dir, 0o700, False) - self.assertTrue(os.path.exists(new_dir)) - self.assertEqual(mock_lock.call_count, 1) + assert os.path.exists(new_dir) + assert mock_lock.call_count == 1 @mock.patch('certbot.util.make_or_verify_dir') def test_failure(self, mock_make_or_verify): mock_make_or_verify.side_effect = OSError - self.assertRaises(errors.Error, self._call, self.tempdir, 0o700, False) + with pytest.raises(errors.Error): + self._call(self.tempdir, 0o700, False) class MakeOrVerifyDirTest(test_util.TempDirTestCase): @@ -174,20 +177,22 @@ class MakeOrVerifyDirTest(test_util.TempDirTestCase): def test_creates_dir_when_missing(self): path = os.path.join(self.tempdir, "bar") self._call(path, 0o650) - self.assertTrue(os.path.isdir(path)) - self.assertTrue(filesystem.check_mode(path, 0o650)) + assert os.path.isdir(path) + assert filesystem.check_mode(path, 0o650) def test_existing_correct_mode_does_not_fail(self): self._call(self.path, 0o600) - self.assertTrue(filesystem.check_mode(self.path, 0o600)) + assert filesystem.check_mode(self.path, 0o600) def test_existing_wrong_mode_fails(self): - self.assertRaises(errors.Error, self._call, self.path, 0o400) + with pytest.raises(errors.Error): + self._call(self.path, 0o400) def test_reraises_os_error(self): with mock.patch.object(filesystem, "makedirs") as makedirs: makedirs.side_effect = OSError() - self.assertRaises(OSError, self._call, "bar", 12312312) + with pytest.raises(OSError): + self._call("bar", 12312312) class UniqueFileTest(test_util.TempDirTestCase): @@ -207,13 +212,13 @@ class UniqueFileTest(test_util.TempDirTestCase): fd.write("bar") fd.close() with open(name) as f: - self.assertEqual(f.read(), "bar") + assert f.read() == "bar" def test_right_mode(self): fd1, name1 = self._call(0o700) fd2, name2 = self._call(0o600) - self.assertTrue(filesystem.check_mode(name1, 0o700)) - self.assertTrue(filesystem.check_mode(name2, 0o600)) + assert filesystem.check_mode(name1, 0o700) + assert filesystem.check_mode(name2, 0o600) fd1.close() fd2.close() @@ -222,20 +227,20 @@ class UniqueFileTest(test_util.TempDirTestCase): fd2, name2 = self._call() fd3, name3 = self._call() - self.assertNotEqual(name1, name2) - self.assertNotEqual(name1, name3) - self.assertNotEqual(name2, name3) + assert name1 != name2 + assert name1 != name3 + assert name2 != name3 - self.assertEqual(os.path.dirname(name1), self.tempdir) - self.assertEqual(os.path.dirname(name2), self.tempdir) - self.assertEqual(os.path.dirname(name3), self.tempdir) + assert os.path.dirname(name1) == self.tempdir + assert os.path.dirname(name2) == self.tempdir + assert os.path.dirname(name3) == self.tempdir basename1 = os.path.basename(name2) - self.assertTrue(basename1.endswith("foo.txt")) + assert basename1.endswith("foo.txt") basename2 = os.path.basename(name2) - self.assertTrue(basename2.endswith("foo.txt")) + assert basename2.endswith("foo.txt") basename3 = os.path.basename(name3) - self.assertTrue(basename3.endswith("foo.txt")) + assert basename3.endswith("foo.txt") fd1.close() fd2.close() @@ -258,8 +263,8 @@ class UniqueLineageNameTest(test_util.TempDirTestCase): def test_basic(self): f, path = self._call("wow") - self.assertIsInstance(f, file_type) - self.assertEqual(os.path.join(self.tempdir, "wow.conf"), path) + assert isinstance(f, file_type) + assert os.path.join(self.tempdir, "wow.conf") == path f.close() def test_multiple(self): @@ -267,15 +272,16 @@ class UniqueLineageNameTest(test_util.TempDirTestCase): for _ in range(10): items.append(self._call("wow")) f, name = items[-1] - self.assertIsInstance(f, file_type) - self.assertIsInstance(name, str) - self.assertIn("wow-0009.conf", name) + assert isinstance(f, file_type) + assert isinstance(name, str) + assert "wow-0009.conf" in name for f, _ in items: f.close() def test_failure(self): with mock.patch("certbot.compat.filesystem.open", side_effect=OSError(errno.EIO)): - self.assertRaises(OSError, self._call, "wow") + with pytest.raises(OSError): + self._call("wow") class SafelyRemoveTest(test_util.TempDirTestCase): @@ -294,17 +300,18 @@ class SafelyRemoveTest(test_util.TempDirTestCase): with open(self.path, "w"): pass # just create the file self._call() - self.assertFalse(os.path.exists(self.path)) + assert not os.path.exists(self.path) def test_missing(self): self._call() # no error, yay! - self.assertFalse(os.path.exists(self.path)) + assert not os.path.exists(self.path) def test_other_error_passthrough(self): with mock.patch("certbot.util.os.remove") as mock_remove: mock_remove.side_effect = OSError - self.assertRaises(OSError, self._call) + with pytest.raises(OSError): + self._call() class SafeEmailTest(unittest.TestCase): @@ -321,7 +328,7 @@ class SafeEmailTest(unittest.TestCase): "abc_def.jdk@hotmail.museum", ] for addr in addrs: - self.assertTrue(self._call(addr), "%s failed." % addr) + assert self._call(addr), "%s failed." % addr def test_invalid_emails(self): addrs = [ @@ -330,7 +337,7 @@ class SafeEmailTest(unittest.TestCase): "~/abc_def.jdk@hotmail.museum", ] for addr in addrs: - self.assertFalse(self._call(addr), "%s failed." % addr) + assert not self._call(addr), "%s failed." % addr class AddDeprecatedArgumentTest(unittest.TestCase): @@ -346,17 +353,17 @@ class AddDeprecatedArgumentTest(unittest.TestCase): self._call("--old-option", 0) with mock.patch("warnings.warn") as mock_warn: self.parser.parse_args(["--old-option"]) - self.assertEqual(mock_warn.call_count, 1) - self.assertIn("is deprecated", mock_warn.call_args[0][0]) - self.assertIn("--old-option", mock_warn.call_args[0][0]) + assert mock_warn.call_count == 1 + assert "is deprecated" in mock_warn.call_args[0][0] + assert "--old-option" in mock_warn.call_args[0][0] def test_warning_with_arg(self): self._call("--old-option", 1) with mock.patch("warnings.warn") as mock_warn: self.parser.parse_args(["--old-option", "42"]) - self.assertEqual(mock_warn.call_count, 1) - self.assertIn("is deprecated", mock_warn.call_args[0][0]) - self.assertIn("--old-option", mock_warn.call_args[0][0]) + assert mock_warn.call_count == 1 + assert "is deprecated" in mock_warn.call_args[0][0] + assert "--old-option" in mock_warn.call_args[0][0] def test_help(self): self._call("--old-option", 2) @@ -366,7 +373,7 @@ class AddDeprecatedArgumentTest(unittest.TestCase): self.parser.parse_args(["-h"]) except SystemExit: pass - self.assertNotIn("--old-option", stdout.getvalue()) + assert "--old-option" not in stdout.getvalue() def test_set_constant(self): """Test when ACTION_TYPES_THAT_DONT_NEED_A_VALUE is a set. @@ -389,8 +396,7 @@ class AddDeprecatedArgumentTest(unittest.TestCase): mock_configargparse.ACTION_TYPES_THAT_DONT_NEED_A_VALUE = typ() self._call("--old-option", 1) self._call("--old-option2", 2) - self.assertEqual( - len(mock_configargparse.ACTION_TYPES_THAT_DONT_NEED_A_VALUE), 1) + assert len(mock_configargparse.ACTION_TYPES_THAT_DONT_NEED_A_VALUE) == 1 class EnforceLeValidity(unittest.TestCase): @@ -400,32 +406,36 @@ class EnforceLeValidity(unittest.TestCase): return enforce_le_validity(domain) def test_sanity(self): - self.assertRaises(errors.ConfigurationError, self._call, u"..") + with pytest.raises(errors.ConfigurationError): + self._call(u"..") def test_invalid_chars(self): - self.assertRaises( - errors.ConfigurationError, self._call, u"hello_world.example.com") + with pytest.raises(errors.ConfigurationError): + self._call(u"hello_world.example.com") def test_leading_hyphen(self): - self.assertRaises( - errors.ConfigurationError, self._call, u"-a.example.com") + with pytest.raises(errors.ConfigurationError): + self._call(u"-a.example.com") def test_trailing_hyphen(self): - self.assertRaises( - errors.ConfigurationError, self._call, u"a-.example.com") + with pytest.raises(errors.ConfigurationError): + self._call(u"a-.example.com") def test_one_label(self): - self.assertRaises(errors.ConfigurationError, self._call, u"com") + with pytest.raises(errors.ConfigurationError): + self._call(u"com") def test_valid_domain(self): - self.assertEqual(self._call(u"example.com"), u"example.com") + assert self._call(u"example.com") == u"example.com" def test_input_with_scheme(self): - self.assertRaises(errors.ConfigurationError, self._call, u"http://example.com") - self.assertRaises(errors.ConfigurationError, self._call, u"https://example.com") + with pytest.raises(errors.ConfigurationError): + self._call(u"http://example.com") + with pytest.raises(errors.ConfigurationError): + self._call(u"https://example.com") def test_valid_input_with_scheme_name(self): - self.assertEqual(self._call(u"http.example.com"), u"http.example.com") + assert self._call(u"http.example.com") == u"http.example.com" class EnforceDomainSanityTest(unittest.TestCase): @@ -436,17 +446,17 @@ class EnforceDomainSanityTest(unittest.TestCase): return enforce_domain_sanity(domain) def test_nonascii_str(self): - self.assertRaises(errors.ConfigurationError, self._call, - u"eichh\u00f6rnchen.example.com".encode("utf-8")) + with pytest.raises(errors.ConfigurationError): + self._call(u"eichh\u00f6rnchen.example.com".encode("utf-8")) def test_nonascii_unicode(self): - self.assertRaises(errors.ConfigurationError, self._call, - u"eichh\u00f6rnchen.example.com") + with pytest.raises(errors.ConfigurationError): + self._call(u"eichh\u00f6rnchen.example.com") def test_too_long(self): long_domain = u"a"*256 - self.assertRaises(errors.ConfigurationError, self._call, - long_domain) + with pytest.raises(errors.ConfigurationError): + self._call(long_domain) def test_not_too_long(self): not_too_long_domain = u"{0}.{1}.{2}.{3}".format("a"*63, "b"*63, "c"*63, "d"*63) @@ -454,23 +464,23 @@ class EnforceDomainSanityTest(unittest.TestCase): def test_empty_label(self): empty_label_domain = u"fizz..example.com" - self.assertRaises(errors.ConfigurationError, self._call, - empty_label_domain) + with pytest.raises(errors.ConfigurationError): + self._call(empty_label_domain) def test_empty_trailing_label(self): empty_trailing_label_domain = u"example.com.." - self.assertRaises(errors.ConfigurationError, self._call, - empty_trailing_label_domain) + with pytest.raises(errors.ConfigurationError): + self._call(empty_trailing_label_domain) def test_long_label_1(self): long_label_domain = u"a"*64 - self.assertRaises(errors.ConfigurationError, self._call, - long_label_domain) + with pytest.raises(errors.ConfigurationError): + self._call(long_label_domain) def test_long_label_2(self): long_label_domain = u"{0}.{1}.com".format(u"a"*64, u"b"*63) - self.assertRaises(errors.ConfigurationError, self._call, - long_label_domain) + with pytest.raises(errors.ConfigurationError): + self._call(long_label_domain) def test_not_long_label(self): not_too_long_label_domain = u"{0}.{1}.com".format(u"a"*63, u"b"*63) @@ -478,8 +488,8 @@ class EnforceDomainSanityTest(unittest.TestCase): def test_empty_domain(self): empty_domain = u"" - self.assertRaises(errors.ConfigurationError, self._call, - empty_domain) + with pytest.raises(errors.ConfigurationError): + self._call(empty_domain) def test_punycode_ok(self): # Punycode is now legal, so no longer an error; instead check @@ -499,12 +509,12 @@ class IsWildcardDomainTest(unittest.TestCase): return is_wildcard_domain(domain) def test_no_wildcard(self): - self.assertFalse(self._call(self.no_wildcard)) - self.assertFalse(self._call(self.no_wildcard.encode())) + assert not self._call(self.no_wildcard) + assert not self._call(self.no_wildcard.encode()) def test_wildcard(self): - self.assertTrue(self._call(self.wildcard)) - self.assertTrue(self._call(self.wildcard.encode())) + assert self._call(self.wildcard) + assert self._call(self.wildcard.encode()) class OsInfoTest(unittest.TestCase): @@ -516,8 +526,8 @@ class OsInfoTest(unittest.TestCase): import certbot.util as cbutil m_distro.like.return_value = "first debian third" id_likes = cbutil.get_systemd_os_like() - self.assertEqual(len(id_likes), 3) - self.assertIn("debian", id_likes) + assert len(id_likes) == 3 + assert "debian" in id_likes @mock.patch("certbot.util.distro") @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux") @@ -528,11 +538,11 @@ class OsInfoTest(unittest.TestCase): m_distro.version.return_value = "1.0" # empty value on first call for fallback to "get_python_os_info" in get_os_info_ua m_distro.name.side_effect = ["", "something", "something"] - self.assertEqual(cbutil.get_os_info_ua(), - " ".join(cbutil.get_python_os_info(pretty=True))) + assert cbutil.get_os_info_ua() == \ + " ".join(cbutil.get_python_os_info(pretty=True)) m_distro.name.side_effect = ["whatever"] - self.assertEqual(cbutil.get_os_info_ua(), "whatever") + assert cbutil.get_os_info_ua() == "whatever" @mock.patch("certbot.util.distro") @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux") @@ -542,36 +552,36 @@ class OsInfoTest(unittest.TestCase): m_distro.id.return_value = "name" m_distro.version.return_value = "version" mock_platform.return_value = "linux" - self.assertEqual(cbutil.get_os_info(), ("name", "version")) + assert cbutil.get_os_info() == ("name", "version") m_distro.id.return_value = "something" m_distro.version.return_value = "else" - self.assertEqual(cbutil.get_os_info(), ("something", "else")) + assert cbutil.get_os_info() == ("something", "else") def test_non_systemd_os_info(self): import certbot.util as cbutil with mock.patch('certbot.util._USE_DISTRO', False): with mock.patch('platform.system_alias', return_value=('NonSystemD', '42', '42')): - self.assertEqual(cbutil.get_python_os_info()[0], 'nonsystemd') + assert cbutil.get_python_os_info()[0] == 'nonsystemd' with mock.patch('platform.system_alias', return_value=('darwin', '', '')): with mock.patch("subprocess.run") as run_mock: run_mock().stdout = '42.42.42' - self.assertEqual(cbutil.get_python_os_info()[0], 'darwin') - self.assertEqual(cbutil.get_python_os_info()[1], '42.42.42') + assert cbutil.get_python_os_info()[0] == 'darwin' + assert cbutil.get_python_os_info()[1] == '42.42.42' with mock.patch('platform.system_alias', return_value=('freebsd', '9.3-RC3-p1', '')): - self.assertEqual(cbutil.get_python_os_info(), ("freebsd", "9")) + assert cbutil.get_python_os_info() == ("freebsd", "9") with mock.patch('platform.system_alias', return_value=('windows', '', '')): with mock.patch('platform.win32_ver', return_value=('4242', '95', '2', '')): - self.assertEqual(cbutil.get_python_os_info(), - ("windows", "95")) + assert cbutil.get_python_os_info() == \ + ("windows", "95") @mock.patch("certbot.util.distro") @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux") @@ -579,7 +589,7 @@ class OsInfoTest(unittest.TestCase): import certbot.util as cbutil m_distro.id.return_value = "" m_distro.version.return_value = "" - self.assertEqual(cbutil.get_python_os_info()[0], "linux") + assert cbutil.get_python_os_info()[0] == "linux" @mock.patch("certbot.util.distro") @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux") @@ -587,7 +597,7 @@ class OsInfoTest(unittest.TestCase): import certbot.util as cbutil m_distro.id.return_value = "testdist" m_distro.version.return_value = "42" - self.assertEqual(cbutil.get_python_os_info(), ("testdist", "42")) + assert cbutil.get_python_os_info() == ("testdist", "42") class AtexitRegisterTest(unittest.TestCase): @@ -608,7 +618,7 @@ class AtexitRegisterTest(unittest.TestCase): def test_not_called(self): self._test_common(initial_pid=-1) - self.assertIs(self.func.called, False) + assert self.func.called is False def _test_common(self, initial_pid): with mock.patch('certbot.util._INITIAL_PID', initial_pid): @@ -616,7 +626,7 @@ class AtexitRegisterTest(unittest.TestCase): self._call(self.func, *self.args, **self.kwargs) # _INITIAL_PID must be mocked when calling atexit_func - self.assertTrue(mock_atexit.register.called) + assert mock_atexit.register.called args, kwargs = mock_atexit.register.call_args atexit_func = args[0] atexit_func(*args[1:], **kwargs) @@ -643,16 +653,16 @@ class ParseLooseVersionTest(unittest.TestCase): ('0.960923', '2.2beta29'), ('1.13++', '5.5.kw')) for v1, v2 in comparisons: - self.assertLess(self._call(v1), self._call(v2)) + assert self._call(v1) < self._call(v2) def test_equal(self): - self.assertEqual(self._call('8.02'), self._call('8.02')) + assert self._call('8.02') == self._call('8.02') def test_greater_than(self): comparisons = (('161', '3.10a'), ('3.2.pl0', '3.1.1.6')) for v1, v2 in comparisons: - self.assertGreater(self._call(v1), self._call(v2)) + assert self._call(v1) > self._call(v2) if __name__ == "__main__": From 2a7eeef17643526cd5ee32d8ae23850c96e3c33e Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 16 Feb 2023 11:17:47 -0800 Subject: [PATCH 44/57] Polish snap_build.py (#9584) I wanted to try to make our tooling's messaging about it a little clearer. While fixing my typo/bad English, we happened to hit a "Chroot problem" failure! See the logs for the CI first attempt at https://dev.azure.com/certbot/certbot/_build/results?buildId=6416&view=results. Looking at these logs, I noticed three things: 1. This message I added is sometimes printed many times because we're still processing output from snapcraft. See https://dev.azure.com/certbot/certbot/_build/results?buildId=6416&view=logs&j=f44d40a4-7318-5ffe-762c-ae4557889284&s=1dfbc15b-7d0f-52a9-b1da-b17592bf94f8&t=07786725-57f8-5198-4d13-ea77f640bd5c&l=565. 2. snapcraft is complaining that we should be using --build-for now instead of --build-on. See https://dev.azure.com/certbot/certbot/_build/results?buildId=6416&view=logs&j=f44d40a4-7318-5ffe-762c-ae4557889284&s=1dfbc15b-7d0f-52a9-b1da-b17592bf94f8&t=07786725-57f8-5198-4d13-ea77f640bd5c&l=472. 3. Us canceling the Certbot build due to a "Chroot problem" happened 3 times in 3 seconds which seems very unlikely. See https://dev.azure.com/certbot/certbot/_build/results?buildId=6416&view=logs&j=f44d40a4-7318-5ffe-762c-ae4557889284&s=1dfbc15b-7d0f-52a9-b1da-b17592bf94f8&t=07786725-57f8-5198-4d13-ea77f640bd5c&l=587. I looked at the builds on launchpad and I only saw one Certbot build. I think what's happening is this code is causing the old build state to be reported so we error immediately. I fixed all of these things in my follow up commits. * polish chroot problem messaging * only execute branch once --- tools/snap/build_remote.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/tools/snap/build_remote.py b/tools/snap/build_remote.py index 7a4eea1b0..092acfa3e 100755 --- a/tools/snap/build_remote.py +++ b/tools/snap/build_remote.py @@ -48,7 +48,7 @@ def _snap_log_name(target: str, arch: str): def _execute_build( target: str, archs: Set[str], status: Dict[str, Dict[str, str]], - workspace: str) -> Tuple[int, List[str]]: + workspace: str, output_lock: Lock) -> Tuple[int, List[str]]: # snapcraft remote-build accepts a --build-id flag with snapcraft version # 5.0+. We make use of this feature to set a unique build ID so a fresh @@ -68,18 +68,28 @@ def _execute_build( environ['XDG_CACHE_HOME'] = tempdir process = subprocess.Popen([ 'snapcraft', 'remote-build', '--launchpad-accept-public-upload', - '--build-on', ','.join(archs), '--build-id', build_id], + '--build-for', ','.join(archs), '--build-id', build_id], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, env=environ, cwd=workspace) + killed = False process_output: List[str] = [] for line in process.stdout: process_output.append(line) _extract_state(target, line, status) - if any(state for state in status[target].values() if state == 'Chroot problem'): - # On this error the snapcraft process stales. Let's finish it. + if not killed and any(state for state in status[target].values() if state == 'Chroot problem'): + # On this error the snapcraft process hangs. Let's finish it. + # + # killed is used to stop us from executing this code path + # multiple times per build that encounters "Chroot problem". + with output_lock: + print('Chroot problem encountered for build ' + f'{target} for {",".join(archs)}.\n' + 'Launchpad seems to be unable to recover from this ' + 'state so we are terminating the build.') process.kill() + killed = True process_state = process.wait() @@ -89,8 +99,6 @@ def _execute_build( def _build_snap( target: str, archs: Set[str], status: Dict[str, Dict[str, str]], running: Dict[str, bool], output_lock: Lock) -> bool: - status[target] = {arch: '...' for arch in archs} - if target == 'certbot': workspace = CERTBOT_DIR else: @@ -99,7 +107,10 @@ def _build_snap( build_success = False retry = 3 while retry: - exit_code, process_output = _execute_build(target, archs, status, workspace) + # Let's reset the status before each build so we're not starting with + # old state values. + status[target] = {arch: '...' for arch in archs} + exit_code, process_output = _execute_build(target, archs, status, workspace, output_lock) with output_lock: print(f'Build {target} for {",".join(archs)} (attempt {4-retry}/3) ended with ' f'exit code {exit_code}.') From 1cb48eca58c2e3133edd6230ac39c10ee78916f7 Mon Sep 17 00:00:00 2001 From: ohemorange Date: Wed, 22 Feb 2023 12:16:28 -0800 Subject: [PATCH 45/57] Remove update symlinks (#9592) * Add deprecation warning when update_symlinks is run * Remove information about update_symlinks from help * ignore our own warning and remove unused imports * Update changelog --- certbot/CHANGELOG.md | 3 ++- certbot/certbot/_internal/cli/group_adder.py | 2 +- certbot/certbot/_internal/cli/verb_help.py | 9 --------- certbot/certbot/_internal/main.py | 2 ++ pytest.ini | 3 +++ 5 files changed, 8 insertions(+), 11 deletions(-) diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index 87ead3bab..af844d931 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -6,7 +6,8 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). ### Added -* +* We deprecated support for the update_symlinks command. Support will be removed in a following + version of Certbot. ### Changed diff --git a/certbot/certbot/_internal/cli/group_adder.py b/certbot/certbot/_internal/cli/group_adder.py index 1bbbe0215..69cb34383 100644 --- a/certbot/certbot/_internal/cli/group_adder.py +++ b/certbot/certbot/_internal/cli/group_adder.py @@ -16,7 +16,7 @@ def _add_all_groups(helpful: "helpful.HelpfulArgumentParser") -> None: helpful.add_group("paths", description="Flags for changing execution paths & servers") helpful.add_group("manage", description="Various subcommands and flags are available for managing your certificates:", - verbs=["certificates", "delete", "renew", "revoke", "update_symlinks", "reconfigure"]) + verbs=["certificates", "delete", "renew", "revoke", "reconfigure"]) # VERBS for verb, docs in VERB_HELP: diff --git a/certbot/certbot/_internal/cli/verb_help.py b/certbot/certbot/_internal/cli/verb_help.py index 9f805035e..f73b2b46a 100644 --- a/certbot/certbot/_internal/cli/verb_help.py +++ b/certbot/certbot/_internal/cli/verb_help.py @@ -1,7 +1,5 @@ """This module contain help information for verbs supported by certbot""" from certbot._internal.cli.cli_constants import SHORT_USAGE -from certbot._internal.cli.cli_utils import flag_default -from certbot.compat import os # The attributes here are: # short: a string that will be displayed by "certbot -h commands" @@ -84,13 +82,6 @@ VERB_HELP = [ "opts": 'Options for the "plugins" subcommand', "usage": "\n\n certbot plugins [options]\n\n" }), - ("update_symlinks", { - "short": "Recreate symlinks in your /etc/letsencrypt/live/ directory", - "opts": ("Recreates certificate and key symlinks in {0}, if you changed them by hand " - "or edited a renewal configuration file".format( - os.path.join(flag_default("config_dir"), "live"))), - "usage": "\n\n certbot update_symlinks [options]\n\n" - }), ("enhance", { "short": "Add security enhancements to your existing configuration", "opts": ("Helps to harden the TLS configuration by adding security enhancements " diff --git a/certbot/certbot/_internal/main.py b/certbot/certbot/_internal/main.py index a8950a151..880850db0 100644 --- a/certbot/certbot/_internal/main.py +++ b/certbot/certbot/_internal/main.py @@ -15,6 +15,7 @@ from typing import Optional from typing import Tuple from typing import TypeVar from typing import Union +import warnings import configobj import josepy as jose @@ -1279,6 +1280,7 @@ def update_symlinks(config: configuration.NamespaceConfig, :rtype: None """ + warnings.warn("update_symlinks is deprecated and will be removed", PendingDeprecationWarning) cert_manager.update_live_symlinks(config) diff --git a/pytest.ini b/pytest.ini index b0c4fe1dc..17bf5afc4 100644 --- a/pytest.ini +++ b/pytest.ini @@ -19,8 +19,11 @@ # unit tests. This warning should be ignored until our (transitive) # dependency on requests-toolbelt is removed or our pinned version can be # updated. +# 4) Ignore our own PendingDeprecationWarning about update_symlinks soon to be dropped. +# See https://github.com/certbot/certbot/issues/6284. filterwarnings = error ignore:decodestring\(\) is a deprecated alias:DeprecationWarning:dns ignore:.*rsyncdir:DeprecationWarning ignore:'urllib3.contrib.pyopenssl:DeprecationWarning:requests_toolbelt + ignore:update_symlinks is deprecated:PendingDeprecationWarning From a42cffc3517776e53df3750ce8c981db67f029e5 Mon Sep 17 00:00:00 2001 From: humanoid2050 <18317508+humanoid2050@users.noreply.github.com> Date: Wed, 22 Feb 2023 20:53:45 -0500 Subject: [PATCH 46/57] generate multiarch images for non-architecture tags (#9586) * generate multiarch images for non-architecture tags * lock docker build to legacy docker buider, and bugfix * rename deploy.sh to deploy_by_arch.sh * Update documentation related to multiarch Docker * Consistent IFS value with respect to other scripts Co-authored-by: humanoid2050 Co-authored-by: Brad Warren --- .../templates/stages/deploy-stage.yml | 49 ++++++++++++------- certbot/CHANGELOG.md | 2 +- tools/docker/README.md | 20 +++++--- tools/docker/build.sh | 4 +- tools/docker/{deploy.sh => deploy_by_arch.sh} | 35 +++++-------- tools/docker/deploy_multiarch.sh | 36 ++++++++++++++ 6 files changed, 94 insertions(+), 52 deletions(-) rename tools/docker/{deploy.sh => deploy_by_arch.sh} (64%) create mode 100755 tools/docker/deploy_multiarch.sh diff --git a/.azure-pipelines/templates/stages/deploy-stage.yml b/.azure-pipelines/templates/stages/deploy-stage.yml index cb8b24e28..f04242751 100644 --- a/.azure-pipelines/templates/stages/deploy-stage.yml +++ b/.azure-pipelines/templates/stages/deploy-stage.yml @@ -11,7 +11,23 @@ stages: - template: ../jobs/snap-deploy-job.yml parameters: snapReleaseChannel: ${{ parameters.snapReleaseChannel }} - - job: publish_docker + # The credentials used in the following jobs are for the shared + # certbotbot account on Docker Hub. The credentials are stored + # in a service account which was created by following the + # instructions at + # https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#sep-docreg. + # The name given to this service account must match the value + # given to containerRegistry below. The authentication used when + # creating this service account was a personal access token + # rather than a password to bypass 2FA. When Brad set this up, + # Azure Pipelines failed to verify the credentials with an error + # like "access is forbidden with a JWT issued from a personal + # access token", but after saving them without verification, the + # access token worked when the pipeline actually ran. "Grant + # access to all pipelines" should also be checked on the service + # account. The access token can be deleted on Docker Hub if + # these credentials need to be revoked. + - job: publish_docker_by_arch pool: vmImage: ubuntu-22.04 strategy: @@ -33,22 +49,19 @@ stages: - task: Docker@2 inputs: command: login - # The credentials used here are for the shared certbotbot account - # on Docker Hub. The credentials are stored in a service account - # which was created by following the instructions at - # https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#sep-docreg. - # The name given to this service account must match the value - # given to containerRegistry below. The authentication used when - # creating this service account was a personal access token - # rather than a password to bypass 2FA. When Brad set this up, - # Azure Pipelines failed to verify the credentials with an error - # like "access is forbidden with a JWT issued from a personal - # access token", but after saving them without verification, the - # access token worked when the pipeline actually ran. "Grant - # access to all pipelines" should also be checked on the service - # account. The access token can be deleted on Docker Hub if - # these credentials need to be revoked. containerRegistry: docker-hub displayName: Login to Docker Hub - - bash: set -e && tools/docker/deploy.sh $(dockerTag) $DOCKER_ARCH - displayName: Deploy the Docker images + - bash: set -e && tools/docker/deploy_by_arch.sh $(dockerTag) $DOCKER_ARCH + displayName: Deploy the Docker images by architecture + - job: publish_docker_multiarch + dependsOn: publish_docker_by_arch + pool: + vmImage: ubuntu-22.04 + steps: + - task: Docker@2 + inputs: + command: login + containerRegistry: docker-hub + displayName: Login to Docker Hub + - bash: set -e && tools/docker/deploy_multiarch.sh $(dockerTag) + displayName: Deploy the Docker multiarch manifests diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index af844d931..e462d294a 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -11,7 +11,7 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). ### Changed -* +* Docker build and deploy scripts now generate multiarch manifests for non-architecture-specific tags, instead of defaulting to amd64 images. ### Fixed diff --git a/tools/docker/README.md b/tools/docker/README.md index 799ddcd0b..19a69935f 100644 --- a/tools/docker/README.md +++ b/tools/docker/README.md @@ -20,12 +20,18 @@ DNS plugin Docker images to Docker Hub. High-level behavior ------------------- -Running `./build.sh all && ./deploy.sh all` causes the Docker -images to be built and deployed to Docker Hub for all supported architectures -where `` is the base of the tag that should be given to the given images. -The tag should either be `nightly` or a git version tag like `v0.34.0`. The -given tag is only the base of the tag because the CPU architecture is also -added to the tag. +Running `./build.sh all` causes the Docker images to be built for all +supported architectures, where `` is the base of the tag that should be +given to the generated images. The tag should either be `nightly` or a git +version tag like `v2.2.0`. The given tag is only the base of the tag because +the CPU architecture is also added to the tag. For version tags above `v2.0.0`, +Additional tags for `latest` are also generated. The generated images are stored +in the local docker image cache. + +Running `./deploy_by_arch.sh all && ./deploy_multiarch.sh ` will +push the previously generated images to Docker Hub and then generate multi-arch +manifests for easy access to the underlying images appropriate for a given +architecture. Configuration ------------- @@ -33,4 +39,4 @@ Configuration To run these scripts you need: 1. An x86_64 machine with Docker installed and the Docker daemon running. You probably don't want to use the docker snap as these scripts have failed when using that in the past. -2. To be logged into Docker Hub with an account able to push to the Certbot and Certbot DNS Docker images on Docker Hub. +2. To be logged into Docker Hub with an account able to push to the Certbot and Certbot DNS Docker images on Docker Hub. Altering the value of `DOCKER_HUB_ORG` in `lib/common` will allow you to push to your own account for testing. diff --git a/tools/docker/build.sh b/tools/docker/build.sh index e3ff5707a..3b4916060 100755 --- a/tools/docker/build.sh +++ b/tools/docker/build.sh @@ -79,7 +79,7 @@ for TARGET_ARCH in "${ALL_REQUESTED_ARCH[@]}"; do pushd "${REPO_ROOT}" DownloadQemuStatic "${TARGET_ARCH}" QEMU_ARCH=$(GetQemuArch "${TARGET_ARCH}") - docker build \ + DOCKER_BUILDKIT=0 docker build \ --build-arg TARGET_ARCH="${TARGET_ARCH}" \ --build-arg QEMU_ARCH="${QEMU_ARCH}" \ -f "${WORK_DIR}/core/Dockerfile" \ @@ -97,7 +97,7 @@ for plugin in "${CERTBOT_PLUGINS[@]}"; do for TARGET_ARCH in "${ALL_REQUESTED_ARCH[@]}"; do QEMU_ARCH=$(GetQemuArch "${TARGET_ARCH}") BASE_IMAGE="${DOCKER_HUB_ORG}/certbot:${TARGET_ARCH}-${TAG_BASE}" - docker build \ + DOCKER_BUILDKIT=0 docker build \ --build-arg BASE_IMAGE="${BASE_IMAGE}" \ --build-arg QEMU_ARCH="${QEMU_ARCH}" \ -f "${WORK_DIR}/plugin/Dockerfile" \ diff --git a/tools/docker/deploy.sh b/tools/docker/deploy_by_arch.sh similarity index 64% rename from tools/docker/deploy.sh rename to tools/docker/deploy_by_arch.sh index f9446a991..4323086a1 100755 --- a/tools/docker/deploy.sh +++ b/tools/docker/deploy_by_arch.sh @@ -4,7 +4,7 @@ IFS=$'\n\t' # This script deploys new versions of Certbot and Certbot plugin docker images. -# Usage: ./deploy.sh [TAG] [all|amd64|arm32v6|arm64v8] +# Usage: ./deploy_by_arch.sh [TAG] [all|amd64|arm32v6|arm64v8] # with the [TAG] value corresponding the base of the tag to give the Docker # images and the 2nd value being the architecture to build snaps for. # Values should be something like `v0.34.0` or `nightly`. The given value is @@ -24,19 +24,16 @@ ParseRequestedArch "${2}" # Creates and pushes all Docker images aliases for the requested architectures # set in the environment variable ALL_REQUESTED_ARCH. If the value of the # global variable TAG_BASE is a 2.0.0 or greater version tag such as v2.1.0, -# the "latest" tag is also updated. Tags without the architecture part are also -# created for the default architecture. -# As an example, for amd64 (the default architecture) and the tag v0.35.0, the -# following tags would be created: -# - certbot/certbot:v0.35.0 -# - certbot/certbot:latest -# - certbot/certbot:amd64-latest -# For the architecture arm32v6 and the tag v0.35.0, only the following tag -# would be created: -# - certbot/certbot:arm32v6-latest -# For other tags such as "nightly", aliases are only created for the default -# architecture where the tag "nightly" would be used without an architecture -# part. +# tags for "latest" are also created. Tags such as "nightly" do not recieve +# "latest" tags. +# As an example, for the tag v2.2.0 and the default set of all target +# architectures as of writing this, the following tags would be created: +# - certbot/certbot:amd64-v2.2.0 <- image +# - certbot/certbot:arm32v6-v2.2.0 <- image +# - certbot/certbot:arm64v8-v2.2.0 <- image +# - certbot/certbot:amd64-latest <- image +# - certbot/certbot:arm32v6-latest <- image +# - certbot/certbot:arm64v8-latest <- image # Usage: TagAndPushForAllRequestedArch [IMAGE NAME] # where [IMAGE NAME] is the name of the Docker image in the Docker repository # such as "certbot" or "dns-cloudflare". @@ -51,19 +48,9 @@ TagAndPushForAllRequestedArch() { # added them, we haven't had another timeout, so until we experience # another timeout & can get the deubg logs, we're leaving them in. docker --debug push "${DOCKER_REPO}:${TARGET_ARCH}-${TAG_BASE}" - - # If TAG_BASE is a valid tag for version 2.0.0 or greater if [[ "${TAG_BASE}" =~ ^v([2-9]|[1-9][0-9]+)\.[0-9]+\.[0-9]+$ ]]; then docker tag "${DOCKER_REPO}:${TARGET_ARCH}-${TAG_BASE}" "${DOCKER_REPO}:${TARGET_ARCH}-latest" docker --debug push "${DOCKER_REPO}:${TARGET_ARCH}-latest" - if [ "${TARGET_ARCH}" == "${DEFAULT_ARCH}" ]; then - docker tag "${DOCKER_REPO}:${TARGET_ARCH}-${TAG_BASE}" "${DOCKER_REPO}:latest" - docker --debug push "${DOCKER_REPO}:latest" - fi - fi - if [ "${TARGET_ARCH}" == "${DEFAULT_ARCH}" ]; then - docker tag "${DOCKER_REPO}:${TARGET_ARCH}-${TAG_BASE}" "${DOCKER_REPO}:${TAG_BASE}" - docker --debug push "${DOCKER_REPO}:${TAG_BASE}" fi done } diff --git a/tools/docker/deploy_multiarch.sh b/tools/docker/deploy_multiarch.sh new file mode 100755 index 000000000..cfbf886a6 --- /dev/null +++ b/tools/docker/deploy_multiarch.sh @@ -0,0 +1,36 @@ +#!/bin/bash +set -euxo pipefail +IFS=$'\n\t' + +WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" + +TAG_BASE="$1" # Eg. v0.35.0 or nightly +if [ -z "$TAG_BASE" ]; then + echo "We cannot tag Docker images with an empty string!" >&2 + exit 1 +fi +source "$WORK_DIR/lib/common" + +# Creates multiarch manifests for TAG_BASE, and 'latest' if TAG_BASE > 2.0.0 +# - certbot/certbot:v2.2.0 <- multiarch manifest +# - certbot/certbot:latest <- multiarch manifest +MakeMultiarchManifestForAllTargetArch() { + DOCKER_REPO="${DOCKER_HUB_ORG}/${1}" + SRC_IMAGES=() + for TARGET_ARCH in "${ALL_TARGET_ARCH[@]}"; do + SRC_IMAGES+=("${DOCKER_REPO}:${TARGET_ARCH}-${TAG_BASE}") + done + docker buildx imagetools create -t ${DOCKER_REPO}:${TAG_BASE} "${SRC_IMAGES[@]}" + if [[ "${TAG_BASE}" =~ ^v([2-9]|[1-9][0-9]+)\.[0-9]+\.[0-9]+$ ]]; then + docker buildx imagetools create -t ${DOCKER_REPO}:latest "${SRC_IMAGES[@]}" + fi +} + + +# Step 1: Certbot core Docker +MakeMultiarchManifestForAllTargetArch "certbot" + +# Step 2: Certbot DNS plugins Docker images +for plugin in "${CERTBOT_PLUGINS[@]}"; do + MakeMultiarchManifestForAllTargetArch "${plugin}" +done From 7c840a7dfdef2500f45999cc33c4544a4a822385 Mon Sep 17 00:00:00 2001 From: Alex Zorin Date: Sat, 25 Feb 2023 08:45:19 +1100 Subject: [PATCH 47/57] Revert "nginx: on encountering lua directives, produce a better warning (#9475)" This reverts commit c178fa8c0be8266a6edd9be5973bc1c135734c38. --- .../certbot_nginx/_internal/configurator.py | 4 +- .../certbot_nginx/_internal/nginxparser.py | 19 ------ .../certbot_nginx/_internal/parser.py | 6 -- certbot-nginx/tests/nginxparser_test.py | 63 ------------------- certbot-nginx/tests/parser_test.py | 10 --- .../etc_nginx/unsupported_directives.conf | 11 ---- 6 files changed, 2 insertions(+), 111 deletions(-) delete mode 100644 certbot-nginx/tests/testdata/etc_nginx/unsupported_directives.conf diff --git a/certbot-nginx/certbot_nginx/_internal/configurator.py b/certbot-nginx/certbot_nginx/_internal/configurator.py index 12c6893f9..ec2806ce3 100644 --- a/certbot-nginx/certbot_nginx/_internal/configurator.py +++ b/certbot-nginx/certbot_nginx/_internal/configurator.py @@ -1061,8 +1061,8 @@ class NginxConfigurator(common.Configurator): product_name, product_version = version_matches[0] if product_name != 'nginx': - logger.warning("nginx derivative %s is not officially supported by " - "Certbot.", product_name) + logger.warning("NGINX derivative %s is not officially supported by" + " certbot", product_name) nginx_version = tuple(int(i) for i in product_version.split(".")) diff --git a/certbot-nginx/certbot_nginx/_internal/nginxparser.py b/certbot-nginx/certbot_nginx/_internal/nginxparser.py index 99955447a..1c74cd367 100644 --- a/certbot-nginx/certbot_nginx/_internal/nginxparser.py +++ b/certbot-nginx/certbot_nginx/_internal/nginxparser.py @@ -33,18 +33,6 @@ if TYPE_CHECKING: logger = logging.getLogger(__name__) -class UnsupportedDirectiveException(RuntimeError): - """Exception when encountering an nginx directive which is not supported - by this parser.""" - - directive_name: str - line_no: int - - def __init__(self, directive_name: str, line_no: int) -> None: - self.directive_name = directive_name - self.line_no = line_no - - class RawNginxParser: # pylint: disable=pointless-statement """A class that parses nginx configuration with pyparsing.""" @@ -86,7 +74,6 @@ class RawNginxParser: def __init__(self, source: str) -> None: self.source = source - self.whitespace_token_group.addParseAction(self._check_disallowed_directive) def parse(self) -> ParseResults: """Returns the parsed tree.""" @@ -96,12 +83,6 @@ class RawNginxParser: """Returns the parsed tree as a list.""" return self.parse().asList() - def _check_disallowed_directive(self, _source: str, line: int, results: ParseResults) -> None: - # *_by_lua_block might be first or second result, due to optional leading whitespace - toks = [t for t in results[0:2] if isinstance(t, str) and t.endswith("_by_lua_block")] - if toks: - raise UnsupportedDirectiveException(toks[0], line) - class RawNginxDumper: """A class that dumps nginx configuration from the provided tree.""" diff --git a/certbot-nginx/certbot_nginx/_internal/parser.py b/certbot-nginx/certbot_nginx/_internal/parser.py index d5a00f103..9d24ce242 100644 --- a/certbot-nginx/certbot_nginx/_internal/parser.py +++ b/certbot-nginx/certbot_nginx/_internal/parser.py @@ -223,12 +223,6 @@ class NginxParser: "supported.", item) except pyparsing.ParseException as err: logger.warning("Could not parse file: %s due to %s", item, err) - except nginxparser.UnsupportedDirectiveException as e: - logger.warning( - "%s:%d contained the '%s' directive, which is not supported by Certbot. The " - "file has been ignored, which may prevent Certbot from functioning properly. " - "Consider using the --webroot plugin and manually installing the certificate.", - item, e.line_no, e.directive_name) return trees def _find_config_root(self) -> str: diff --git a/certbot-nginx/tests/nginxparser_test.py b/certbot-nginx/tests/nginxparser_test.py index b4248b85f..44fdfd141 100644 --- a/certbot-nginx/tests/nginxparser_test.py +++ b/certbot-nginx/tests/nginxparser_test.py @@ -14,7 +14,6 @@ from certbot_nginx._internal.nginxparser import load from certbot_nginx._internal.nginxparser import loads from certbot_nginx._internal.nginxparser import RawNginxParser from certbot_nginx._internal.nginxparser import UnspacedList -from certbot_nginx._internal.nginxparser import UnsupportedDirectiveException import test_util as util FIRST = operator.itemgetter(0) @@ -357,68 +356,6 @@ class TestRawNginxParser(unittest.TestCase): parsed = loads("") assert parsed == [] - def test_lua(self): - # https://github.com/certbot/certbot/issues/9066 - with pytest.raises(UnsupportedDirectiveException): - loads(""" - location /foo { - content_by_lua_block { - ngx.say('Hello World') - } - } - """) - - # Without leading whitespace - with pytest.raises(UnsupportedDirectiveException): - loads(""" - location /foo {content_by_lua_block { - ngx.say('Hello World') - } - } - """) - - # Doesn't trigger if it's commented or not in the right position. - parsed = loads(""" - location /foo {server_name content_by_lua_block; - #content_by_lua_block { - # ngx.say('Hello World') - # } - } - """) - assert parsed == \ - [ - [['location', '/foo'], - [['server_name', 'content_by_lua_block'], - ['#', 'content_by_lua_block {'], - ['#', " ngx.say('Hello World')"], - ['#', ' }'] - ]] - ] - - # *_by_lua should parse successfully. - parsed = loads(""" - location / { - set $a 32; - set $b 56; - set_by_lua $sum - 'return tonumber(ngx.arg[1]) + tonumber(ngx.arg[2])' - $a $b; - content_by_lua ' - ngx.say("foo"); - '; - } - """) - assert parsed == \ - [ - [['location', '/'], - [['set', '$a', '32'], - ['set', '$b', '56'], - ['set_by_lua', '$sum', - "'return tonumber(ngx.arg[1]) + tonumber(ngx.arg[2])'", '$a', '$b' - ], - ['content_by_lua', '\'\n ngx.say("foo");\n \''] - ]] - ] class TestUnspacedList(unittest.TestCase): """Test the UnspacedList data structure""" diff --git a/certbot-nginx/tests/parser_test.py b/certbot-nginx/tests/parser_test.py index fea2d9d84..f9cdb819c 100644 --- a/certbot-nginx/tests/parser_test.py +++ b/certbot-nginx/tests/parser_test.py @@ -4,8 +4,6 @@ import re import shutil import sys from typing import List -import unittest -from unittest import mock import pytest @@ -533,14 +531,6 @@ class NginxParserTest(util.NginxTest): for output in log.output ) - @mock.patch('certbot_nginx._internal.parser.logger.warning') - def test_load_unsupported_directive_logged(self, mock_warn): - nparser = parser.NginxParser(self.config_path) - nparser.config_root = nparser.abs_path('unsupported_directives.conf') - nparser.load() - assert mock_warn.call_count == 1 - assert "which is not supported by Certbot" in mock_warn.call_args[0][0] - if __name__ == "__main__": sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover diff --git a/certbot-nginx/tests/testdata/etc_nginx/unsupported_directives.conf b/certbot-nginx/tests/testdata/etc_nginx/unsupported_directives.conf deleted file mode 100644 index d071c68c1..000000000 --- a/certbot-nginx/tests/testdata/etc_nginx/unsupported_directives.conf +++ /dev/null @@ -1,11 +0,0 @@ -# This configuration file contains unsupported direcives. - -server { - listen 80; - - location / { - foobar_by_lua_block { - ngx.say("Hello World") - } - } -} From 1cb8c389b70de2d7f1c83bdf99286eb61b535e93 Mon Sep 17 00:00:00 2001 From: Alex Zorin Date: Sat, 25 Feb 2023 09:32:38 +1100 Subject: [PATCH 48/57] note the issue in the CHANGELOG --- certbot/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index e462d294a..59553ea8c 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -15,7 +15,7 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). ### Fixed -* +* Reverted [#9475](https://github.com/certbot/certbot/pull/9475) due to a performance regression in large nginx deployments. More details about these changes can be found on our GitHub repo. From 34e6b1e74db1f0af21224208cc7a3507d8cbf301 Mon Sep 17 00:00:00 2001 From: Mads Jensen Date: Tue, 28 Feb 2023 00:45:19 +0100 Subject: [PATCH 49/57] Remove redundant OCSPTestOpenSSL.tearDown (#9599) --- certbot/tests/ocsp_test.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/certbot/tests/ocsp_test.py b/certbot/tests/ocsp_test.py index 8dfeaf9a9..0d1404fcb 100644 --- a/certbot/tests/ocsp_test.py +++ b/certbot/tests/ocsp_test.py @@ -37,9 +37,6 @@ class OCSPTestOpenSSL(unittest.TestCase): mock_exists.return_value = True self.checker = ocsp.RevocationChecker(enforce_openssl_binary_usage=True) - def tearDown(self): - pass - @mock.patch('certbot.ocsp.logger.info') @mock.patch('certbot.ocsp.subprocess.run') @mock.patch('certbot.util.exe_exists') From 173b832a8fc27eaa80bae6629d446367349f9572 Mon Sep 17 00:00:00 2001 From: Alexis Date: Tue, 28 Feb 2023 12:38:53 -0800 Subject: [PATCH 50/57] Create Weekly Notification Message for Certbot Team Composes Mattermost message to team channel --- .github/workflows/notify_weekly.yaml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/notify_weekly.yaml diff --git a/.github/workflows/notify_weekly.yaml b/.github/workflows/notify_weekly.yaml new file mode 100644 index 000000000..d259a8021 --- /dev/null +++ b/.github/workflows/notify_weekly.yaml @@ -0,0 +1,25 @@ +name: Weekly Github Update + +on: + schedule: + # Every week on Thursday @ 1:00 + - cron: "0 1 * * 4" +jobs: + send-mattermost-message: + runs-on: ubuntu-latest + + steps: + - name: Create Mattermost Message + run: | + DATE=$(date --date="7 days ago" +"%Y-%m-%d") + MERGED_URL="https://github.com/pulls?q=merged%3A%3E${DATE}+org%3Acertbot+" + UPDATED_URL="https://github.com/pulls?q=updated%3A%3E${DATE}+org%3Acertbot+" + echo "{\"text\":\"## Updates Across Certbot Repos\n\n + - Certbot team members SHOULD look at: [link]($MERGED_URL)\n\n + - Certbot team members MAY also want to look at: [link]($UPDATED_URL)\n\n + - Want to Discuss something today? Place it [here](https://docs.google.com/document/d/17YMUbtC1yg6MfiTMwT8zVm9LmO-cuGVBom0qFn8XJBM/edit?usp=sharing) and we can meet today on Zoom.\n\n + - The key words SHOULD and MAY in this message are to be interpreted as described in [RFC 8147](https://www.rfc-editor.org/rfc/rfc8174). \" + }" > mattermost.json + - uses: mattermost/action-mattermost-notify@master + env: + MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK_URL }} From 44be66eed9c17ee1bbea5ee5923560c694804922 Mon Sep 17 00:00:00 2001 From: Alexis Date: Tue, 28 Feb 2023 17:38:23 -0800 Subject: [PATCH 51/57] Update .github/workflows/notify_weekly.yaml --- .github/workflows/notify_weekly.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/notify_weekly.yaml b/.github/workflows/notify_weekly.yaml index d259a8021..77e09a3e5 100644 --- a/.github/workflows/notify_weekly.yaml +++ b/.github/workflows/notify_weekly.yaml @@ -3,7 +3,7 @@ name: Weekly Github Update on: schedule: # Every week on Thursday @ 1:00 - - cron: "0 1 * * 4" + - cron: "0 13 * * 4" jobs: send-mattermost-message: runs-on: ubuntu-latest From 10b0fb6da0edb0002b9e2bfd62c3a4c3a80ac589 Mon Sep 17 00:00:00 2001 From: Alexis Date: Tue, 28 Feb 2023 17:38:43 -0800 Subject: [PATCH 52/57] Update .github/workflows/notify_weekly.yaml --- .github/workflows/notify_weekly.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/notify_weekly.yaml b/.github/workflows/notify_weekly.yaml index 77e09a3e5..c8c64da3f 100644 --- a/.github/workflows/notify_weekly.yaml +++ b/.github/workflows/notify_weekly.yaml @@ -2,7 +2,7 @@ name: Weekly Github Update on: schedule: - # Every week on Thursday @ 1:00 + # Every week on Thursday @ 13:00 - cron: "0 13 * * 4" jobs: send-mattermost-message: From 87f8eca03347ad84103b8fc8804161b02edec230 Mon Sep 17 00:00:00 2001 From: Alexis Date: Tue, 28 Feb 2023 17:39:17 -0800 Subject: [PATCH 53/57] Update .github/workflows/notify_weekly.yaml Remove trailing char --- .github/workflows/notify_weekly.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/notify_weekly.yaml b/.github/workflows/notify_weekly.yaml index c8c64da3f..3a758db83 100644 --- a/.github/workflows/notify_weekly.yaml +++ b/.github/workflows/notify_weekly.yaml @@ -12,8 +12,8 @@ jobs: - name: Create Mattermost Message run: | DATE=$(date --date="7 days ago" +"%Y-%m-%d") - MERGED_URL="https://github.com/pulls?q=merged%3A%3E${DATE}+org%3Acertbot+" - UPDATED_URL="https://github.com/pulls?q=updated%3A%3E${DATE}+org%3Acertbot+" + MERGED_URL="https://github.com/pulls?q=merged%3A%3E${DATE}+org%3Acertbot" + UPDATED_URL="https://github.com/pulls?q=updated%3A%3E${DATE}+org%3Acertbot" echo "{\"text\":\"## Updates Across Certbot Repos\n\n - Certbot team members SHOULD look at: [link]($MERGED_URL)\n\n - Certbot team members MAY also want to look at: [link]($UPDATED_URL)\n\n From bdd81a5961624dd3eb904adece9a363a04a38908 Mon Sep 17 00:00:00 2001 From: alexzorin Date: Thu, 2 Mar 2023 09:41:00 +1100 Subject: [PATCH 54/57] google: ignore declare_namespace deprecation warnings (#9604) Fixes the nopin build on master. --------- Co-authored-by: Brad Warren --- pytest.ini | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pytest.ini b/pytest.ini index 17bf5afc4..75421bf4a 100644 --- a/pytest.ini +++ b/pytest.ini @@ -21,9 +21,12 @@ # updated. # 4) Ignore our own PendingDeprecationWarning about update_symlinks soon to be dropped. # See https://github.com/certbot/certbot/issues/6284. +# 5) Ignore pkg_resources.declare_namespace used in a large number of Google's Python +# libs. e.g. https://github.com/googleapis/google-auth-library-python/issues/1229. filterwarnings = error ignore:decodestring\(\) is a deprecated alias:DeprecationWarning:dns ignore:.*rsyncdir:DeprecationWarning ignore:'urllib3.contrib.pyopenssl:DeprecationWarning:requests_toolbelt ignore:update_symlinks is deprecated:PendingDeprecationWarning + ignore:.*declare_namespace\('google:DeprecationWarning From cd467f2ce163710b475363ee7f4cb96a65ddebab Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 1 Mar 2023 15:28:20 -0800 Subject: [PATCH 55/57] remove nose cruft (#9603) --- certbot-apache/tests/centos_test.py | 2 -- certbot-apache/tests/debian_test.py | 2 -- certbot-apache/tests/entrypoint_test.py | 2 -- certbot-apache/tests/fedora_test.py | 2 -- certbot-apache/tests/gentoo_test.py | 2 -- 5 files changed, 10 deletions(-) diff --git a/certbot-apache/tests/centos_test.py b/certbot-apache/tests/centos_test.py index dd2108de1..6b0b33377 100644 --- a/certbot-apache/tests/centos_test.py +++ b/certbot-apache/tests/centos_test.py @@ -136,8 +136,6 @@ class UseCorrectApacheExecutableTest(util.ApacheTest): class MultipleVhostsTestCentOS(util.ApacheTest): """Multiple vhost tests for CentOS / RHEL family of distros""" - _multiprocess_can_split_ = True - @mock.patch("certbot.util.get_os_info") def setUp(self, mock_get_os_info): # pylint: disable=arguments-differ test_dir = "centos7_apache/apache" diff --git a/certbot-apache/tests/debian_test.py b/certbot-apache/tests/debian_test.py index ff343b123..ae605264b 100644 --- a/certbot-apache/tests/debian_test.py +++ b/certbot-apache/tests/debian_test.py @@ -17,8 +17,6 @@ import util class MultipleVhostsTestDebian(util.ApacheTest): """Multiple vhost tests for Debian family of distros""" - _multiprocess_can_split_ = True - def setUp(self): # pylint: disable=arguments-differ super().setUp() self.config = util.get_apache_configurator( diff --git a/certbot-apache/tests/entrypoint_test.py b/certbot-apache/tests/entrypoint_test.py index ef5013555..d81d4a04a 100644 --- a/certbot-apache/tests/entrypoint_test.py +++ b/certbot-apache/tests/entrypoint_test.py @@ -12,8 +12,6 @@ from certbot_apache._internal import entrypoint class EntryPointTest(unittest.TestCase): """Entrypoint tests""" - _multiprocess_can_split_ = True - def test_get_configurator(self): with mock.patch("certbot.util.get_os_info") as mock_info: diff --git a/certbot-apache/tests/fedora_test.py b/certbot-apache/tests/fedora_test.py index 353352143..a313feb00 100644 --- a/certbot-apache/tests/fedora_test.py +++ b/certbot-apache/tests/fedora_test.py @@ -83,8 +83,6 @@ class FedoraRestartTest(util.ApacheTest): class MultipleVhostsTestFedora(util.ApacheTest): """Multiple vhost tests for CentOS / RHEL family of distros""" - _multiprocess_can_split_ = True - def setUp(self): # pylint: disable=arguments-differ test_dir = "centos7_apache/apache" config_root = "centos7_apache/apache/httpd" diff --git a/certbot-apache/tests/gentoo_test.py b/certbot-apache/tests/gentoo_test.py index 6399797ed..0774a6e8b 100644 --- a/certbot-apache/tests/gentoo_test.py +++ b/certbot-apache/tests/gentoo_test.py @@ -43,8 +43,6 @@ def get_vh_truth(temp_dir, config_name): class MultipleVhostsTestGentoo(util.ApacheTest): """Multiple vhost tests for non-debian distro""" - _multiprocess_can_split_ = True - def setUp(self): # pylint: disable=arguments-differ test_dir = "gentoo_apache/apache" config_root = "gentoo_apache/apache/apache2" From da01846d34ba564934d0164b47ba65b0c646506b Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Thu, 2 Mar 2023 06:48:40 -0800 Subject: [PATCH 56/57] Remove unnecessary unittest (#9596) Now that we're using pytest more aggressively, I think we should start transitioning our tests to that style rather than continuing to use unittest. This PR removes some unnecessary uses of unittest I found. I kept the test classes (while removing the inheritance from unittest.TestCase) where I felt like it added structure or logical grouping of tests. I verified that pytest still finds all the tests in both this branch and master by running commands like: ``` pytest $(git diff --name-only master | grep -v windows_installer_integration_tests) ``` --- acme/tests/jose_test.py | 75 ++++--- acme/tests/util_test.py | 13 +- certbot-apache/tests/entrypoint_test.py | 55 +++-- certbot-apache/tests/parsernode_test.py | 39 ++-- certbot-apache/tests/parsernode_util_test.py | 196 +++++++++--------- .../test_main.py | 3 +- certbot/tests/compat/misc_test.py | 3 +- certbot/tests/compat/os_test.py | 23 +- certbot/tests/display/util_test.py | 122 +++++------ certbot/tests/helpful_test.py | 13 +- certbot/tests/plugins/util_test.py | 56 +++-- 11 files changed, 273 insertions(+), 325 deletions(-) diff --git a/acme/tests/jose_test.py b/acme/tests/jose_test.py index 67964022d..216bc69ca 100644 --- a/acme/tests/jose_test.py +++ b/acme/tests/jose_test.py @@ -6,51 +6,48 @@ import unittest import pytest -class JoseTest(unittest.TestCase): - """Tests for acme.jose shim.""" +def _test_it(submodule, attribute): + if submodule: + acme_jose_path = 'acme.jose.' + submodule + josepy_path = 'josepy.' + submodule + else: + acme_jose_path = 'acme.jose' + josepy_path = 'josepy' + acme_jose_mod = importlib.import_module(acme_jose_path) + josepy_mod = importlib.import_module(josepy_path) - def _test_it(self, submodule, attribute): - if submodule: - acme_jose_path = 'acme.jose.' + submodule - josepy_path = 'josepy.' + submodule - else: - acme_jose_path = 'acme.jose' - josepy_path = 'josepy' - acme_jose_mod = importlib.import_module(acme_jose_path) - josepy_mod = importlib.import_module(josepy_path) + assert acme_jose_mod is josepy_mod + assert getattr(acme_jose_mod, attribute) is getattr(josepy_mod, attribute) - assert acme_jose_mod is josepy_mod - assert getattr(acme_jose_mod, attribute) is getattr(josepy_mod, attribute) + # We use the imports below with eval, but pylint doesn't + # understand that. + import josepy # pylint: disable=unused-import - # We use the imports below with eval, but pylint doesn't - # understand that. - import josepy # pylint: disable=unused-import + import acme # pylint: disable=unused-import + acme_jose_mod = eval(acme_jose_path) # pylint: disable=eval-used + josepy_mod = eval(josepy_path) # pylint: disable=eval-used + assert acme_jose_mod is josepy_mod + assert getattr(acme_jose_mod, attribute) is getattr(josepy_mod, attribute) - import acme # pylint: disable=unused-import - acme_jose_mod = eval(acme_jose_path) # pylint: disable=eval-used - josepy_mod = eval(josepy_path) # pylint: disable=eval-used - assert acme_jose_mod is josepy_mod - assert getattr(acme_jose_mod, attribute) is getattr(josepy_mod, attribute) +def test_top_level(): + _test_it('', 'RS512') - def test_top_level(self): - self._test_it('', 'RS512') +def test_submodules(): + # This test ensures that the modules in josepy that were + # available at the time it was moved into its own package are + # available under acme.jose. Backwards compatibility with new + # modules or testing code is not maintained. + mods_and_attrs = [('b64', 'b64decode',), + ('errors', 'Error',), + ('interfaces', 'JSONDeSerializable',), + ('json_util', 'Field',), + ('jwa', 'HS256',), + ('jwk', 'JWK',), + ('jws', 'JWS',), + ('util', 'ImmutableMap',),] - def test_submodules(self): - # This test ensures that the modules in josepy that were - # available at the time it was moved into its own package are - # available under acme.jose. Backwards compatibility with new - # modules or testing code is not maintained. - mods_and_attrs = [('b64', 'b64decode',), - ('errors', 'Error',), - ('interfaces', 'JSONDeSerializable',), - ('json_util', 'Field',), - ('jwa', 'HS256',), - ('jwk', 'JWK',), - ('jws', 'JWS',), - ('util', 'ImmutableMap',),] - - for mod, attr in mods_and_attrs: - self._test_it(mod, attr) + for mod, attr in mods_and_attrs: + _test_it(mod, attr) if __name__ == '__main__': diff --git a/acme/tests/util_test.py b/acme/tests/util_test.py index 8df47c5be..8918755fe 100644 --- a/acme/tests/util_test.py +++ b/acme/tests/util_test.py @@ -5,14 +5,11 @@ import unittest import pytest -class MapKeysTest(unittest.TestCase): - """Tests for acme.util.map_keys.""" - - def test_it(self): - from acme.util import map_keys - assert {'a': 'b', 'c': 'd'} == \ - map_keys({'a': 'b', 'c': 'd'}, lambda key: key) - assert {2: 2, 4: 4} == map_keys({1: 2, 3: 4}, lambda x: x + 1) +def test_it(): + from acme.util import map_keys + assert {'a': 'b', 'c': 'd'} == \ + map_keys({'a': 'b', 'c': 'd'}, lambda key: key) + assert {2: 2, 4: 4} == map_keys({1: 2, 3: 4}, lambda x: x + 1) if __name__ == '__main__': diff --git a/certbot-apache/tests/entrypoint_test.py b/certbot-apache/tests/entrypoint_test.py index d81d4a04a..ca4a22400 100644 --- a/certbot-apache/tests/entrypoint_test.py +++ b/certbot-apache/tests/entrypoint_test.py @@ -1,6 +1,5 @@ """Test for certbot_apache._internal.entrypoint for override class resolution""" import sys -import unittest from unittest import mock import pytest @@ -9,38 +8,34 @@ from certbot_apache._internal import configurator from certbot_apache._internal import entrypoint -class EntryPointTest(unittest.TestCase): - """Entrypoint tests""" +def test_get_configurator(): + with mock.patch("certbot.util.get_os_info") as mock_info: + for distro in entrypoint.OVERRIDE_CLASSES: + return_value = (distro, "whatever") + if distro == 'fedora_old': + return_value = ('fedora', '28') + elif distro == 'fedora': + return_value = ('fedora', '29') + mock_info.return_value = return_value + assert entrypoint.get_configurator() == \ + entrypoint.OVERRIDE_CLASSES[distro] - def test_get_configurator(self): - - with mock.patch("certbot.util.get_os_info") as mock_info: - for distro in entrypoint.OVERRIDE_CLASSES: - return_value = (distro, "whatever") - if distro == 'fedora_old': - return_value = ('fedora', '28') - elif distro == 'fedora': - return_value = ('fedora', '29') - mock_info.return_value = return_value +def test_nonexistent_like(): + with mock.patch("certbot.util.get_os_info") as mock_info: + mock_info.return_value = ("nonexistent", "irrelevant") + with mock.patch("certbot.util.get_systemd_os_like") as mock_like: + for like in entrypoint.OVERRIDE_CLASSES: + mock_like.return_value = [like] assert entrypoint.get_configurator() == \ - entrypoint.OVERRIDE_CLASSES[distro] + entrypoint.OVERRIDE_CLASSES[like] - def test_nonexistent_like(self): - with mock.patch("certbot.util.get_os_info") as mock_info: - mock_info.return_value = ("nonexistent", "irrelevant") - with mock.patch("certbot.util.get_systemd_os_like") as mock_like: - for like in entrypoint.OVERRIDE_CLASSES: - mock_like.return_value = [like] - assert entrypoint.get_configurator() == \ - entrypoint.OVERRIDE_CLASSES[like] - - def test_nonexistent_generic(self): - with mock.patch("certbot.util.get_os_info") as mock_info: - mock_info.return_value = ("nonexistent", "irrelevant") - with mock.patch("certbot.util.get_systemd_os_like") as mock_like: - mock_like.return_value = ["unknown"] - assert entrypoint.get_configurator() == \ - configurator.ApacheConfigurator +def test_nonexistent_generic(): + with mock.patch("certbot.util.get_os_info") as mock_info: + mock_info.return_value = ("nonexistent", "irrelevant") + with mock.patch("certbot.util.get_systemd_os_like") as mock_like: + mock_like.return_value = ["unknown"] + assert entrypoint.get_configurator() == \ + configurator.ApacheConfigurator if __name__ == "__main__": diff --git a/certbot-apache/tests/parsernode_test.py b/certbot-apache/tests/parsernode_test.py index 35eb53414..d85e8c753 100644 --- a/certbot-apache/tests/parsernode_test.py +++ b/certbot-apache/tests/parsernode_test.py @@ -1,7 +1,6 @@ """ Tests for ParserNode interface """ import sys -import unittest import pytest @@ -104,27 +103,25 @@ interfaces.CommentNode.register(DummyCommentNode) interfaces.DirectiveNode.register(DummyDirectiveNode) interfaces.BlockNode.register(DummyBlockNode) -class ParserNodeTest(unittest.TestCase): +def test_dummy(): """Dummy placeholder test case for ParserNode interfaces""" - - def test_dummy(self): - dummyblock = DummyBlockNode( - name="None", - parameters=(), - ancestor=None, - dirty=False, - filepath="/some/random/path" - ) - dummydirective = DummyDirectiveNode( - name="Name", - ancestor=None, - filepath="/another/path" - ) - dummycomment = DummyCommentNode( - comment="Comment", - ancestor=dummyblock, - filepath="/some/file" - ) + dummyblock = DummyBlockNode( + name="None", + parameters=(), + ancestor=None, + dirty=False, + filepath="/some/random/path" + ) + dummydirective = DummyDirectiveNode( + name="Name", + ancestor=None, + filepath="/another/path" + ) + dummycomment = DummyCommentNode( + comment="Comment", + ancestor=dummyblock, + filepath="/some/file" + ) if __name__ == "__main__": diff --git a/certbot-apache/tests/parsernode_util_test.py b/certbot-apache/tests/parsernode_util_test.py index 1ccc2495c..c046b1ec7 100644 --- a/certbot-apache/tests/parsernode_util_test.py +++ b/certbot-apache/tests/parsernode_util_test.py @@ -1,123 +1,119 @@ """ Tests for ParserNode utils """ import sys -import unittest import pytest from certbot_apache._internal import parsernode_util as util -class ParserNodeUtilTest(unittest.TestCase): - """Tests for ParserNode utils""" +def _setup_parsernode(): + """ Sets up kwargs dict for ParserNode """ + return { + "ancestor": None, + "dirty": False, + "filepath": "/tmp", + } - def _setup_parsernode(self): - """ Sets up kwargs dict for ParserNode """ - return { - "ancestor": None, - "dirty": False, - "filepath": "/tmp", - } +def _setup_commentnode(): + """ Sets up kwargs dict for CommentNode """ - def _setup_commentnode(self): - """ Sets up kwargs dict for CommentNode """ + pn = _setup_parsernode() + pn["comment"] = "x" + return pn - pn = self._setup_parsernode() - pn["comment"] = "x" - return pn +def _setup_directivenode(): + """ Sets up kwargs dict for DirectiveNode """ - def _setup_directivenode(self): - """ Sets up kwargs dict for DirectiveNode """ + pn = _setup_parsernode() + pn["name"] = "Name" + pn["parameters"] = ("first",) + pn["enabled"] = True + return pn - pn = self._setup_parsernode() - pn["name"] = "Name" - pn["parameters"] = ("first",) - pn["enabled"] = True - return pn +def test_unknown_parameter(): + params = _setup_parsernode() + params["unknown"] = "unknown" + with pytest.raises(TypeError): + util.parsernode_kwargs(params) - def test_unknown_parameter(self): - params = self._setup_parsernode() - params["unknown"] = "unknown" - with pytest.raises(TypeError): - util.parsernode_kwargs(params) - - params = self._setup_commentnode() - params["unknown"] = "unknown" - with pytest.raises(TypeError): - util.commentnode_kwargs(params) - - params = self._setup_directivenode() - params["unknown"] = "unknown" - with pytest.raises(TypeError): - util.directivenode_kwargs(params) - - def test_parsernode(self): - params = self._setup_parsernode() - ctrl = self._setup_parsernode() - - ancestor, dirty, filepath, metadata = util.parsernode_kwargs(params) - assert ancestor == ctrl["ancestor"] - assert dirty == ctrl["dirty"] - assert filepath == ctrl["filepath"] - assert metadata == {} - - def test_parsernode_from_metadata(self): - params = self._setup_parsernode() - params.pop("filepath") - md = {"some": "value"} - params["metadata"] = md - - # Just testing that error from missing required parameters is not raised - _, _, _, metadata = util.parsernode_kwargs(params) - assert metadata == md - - def test_commentnode(self): - params = self._setup_commentnode() - ctrl = self._setup_commentnode() - - comment, _ = util.commentnode_kwargs(params) - assert comment == ctrl["comment"] - - def test_commentnode_from_metadata(self): - params = self._setup_commentnode() - params.pop("comment") - params["metadata"] = {} - - # Just testing that error from missing required parameters is not raised + params = _setup_commentnode() + params["unknown"] = "unknown" + with pytest.raises(TypeError): util.commentnode_kwargs(params) - def test_directivenode(self): - params = self._setup_directivenode() - ctrl = self._setup_directivenode() - - name, parameters, enabled, _ = util.directivenode_kwargs(params) - assert name == ctrl["name"] - assert parameters == ctrl["parameters"] - assert enabled == ctrl["enabled"] - - def test_directivenode_from_metadata(self): - params = self._setup_directivenode() - params.pop("filepath") - params.pop("name") - params["metadata"] = {"irrelevant": "value"} - - # Just testing that error from missing required parameters is not raised + params = _setup_directivenode() + params["unknown"] = "unknown" + with pytest.raises(TypeError): util.directivenode_kwargs(params) - def test_missing_required(self): - c_params = self._setup_commentnode() - c_params.pop("comment") - with pytest.raises(TypeError): - util.commentnode_kwargs(c_params) +def test_parsernode(): + params = _setup_parsernode() + ctrl = _setup_parsernode() - d_params = self._setup_directivenode() - d_params.pop("ancestor") - with pytest.raises(TypeError): - util.directivenode_kwargs(d_params) + ancestor, dirty, filepath, metadata = util.parsernode_kwargs(params) + assert ancestor == ctrl["ancestor"] + assert dirty == ctrl["dirty"] + assert filepath == ctrl["filepath"] + assert metadata == {} - p_params = self._setup_parsernode() - p_params.pop("filepath") - with pytest.raises(TypeError): - util.parsernode_kwargs(p_params) +def test_parsernode_from_metadata(): + params = _setup_parsernode() + params.pop("filepath") + md = {"some": "value"} + params["metadata"] = md + + # Just testing that error from missing required parameters is not raised + _, _, _, metadata = util.parsernode_kwargs(params) + assert metadata == md + +def test_commentnode(): + params = _setup_commentnode() + ctrl = _setup_commentnode() + + comment, _ = util.commentnode_kwargs(params) + assert comment == ctrl["comment"] + +def test_commentnode_from_metadata(): + params = _setup_commentnode() + params.pop("comment") + params["metadata"] = {} + + # Just testing that error from missing required parameters is not raised + util.commentnode_kwargs(params) + +def test_directivenode(): + params = _setup_directivenode() + ctrl = _setup_directivenode() + + name, parameters, enabled, _ = util.directivenode_kwargs(params) + assert name == ctrl["name"] + assert parameters == ctrl["parameters"] + assert enabled == ctrl["enabled"] + +def test_directivenode_from_metadata(): + params = _setup_directivenode() + params.pop("filepath") + params.pop("name") + params["metadata"] = {"irrelevant": "value"} + + # Just testing that error from missing required parameters is not raised + util.directivenode_kwargs(params) + +def test_missing_required(): + c_params = _setup_commentnode() + c_params.pop("comment") + with pytest.raises(TypeError): + util.commentnode_kwargs(c_params) + + d_params = _setup_directivenode() + d_params.pop("ancestor") + with pytest.raises(TypeError): + util.directivenode_kwargs(d_params) + + p_params = _setup_parsernode() + p_params.pop("filepath") + with pytest.raises(TypeError): + util.parsernode_kwargs(p_params) if __name__ == "__main__": diff --git a/certbot-ci/windows_installer_integration_tests/test_main.py b/certbot-ci/windows_installer_integration_tests/test_main.py index be6447a96..635335522 100644 --- a/certbot-ci/windows_installer_integration_tests/test_main.py +++ b/certbot-ci/windows_installer_integration_tests/test_main.py @@ -4,12 +4,11 @@ import re import subprocess import time from typing import Any -import unittest import pytest -@unittest.skipIf(os.name != 'nt', reason='Windows installer tests must be run on Windows.') +@pytest.mark.skipif(os.name != 'nt', reason='Windows installer tests must be run on Windows.') def test_it(request: pytest.FixtureRequest) -> None: try: subprocess.check_call(['certbot', '--version']) diff --git a/certbot/tests/compat/misc_test.py b/certbot/tests/compat/misc_test.py index ff9c2a003..cf76f36cb 100644 --- a/certbot/tests/compat/misc_test.py +++ b/certbot/tests/compat/misc_test.py @@ -1,6 +1,5 @@ """Tests for certbot.compat.misc""" import sys -import unittest from unittest import mock import pytest @@ -8,7 +7,7 @@ import pytest from certbot.compat import os -class ExecuteStatusTest(unittest.TestCase): +class ExecuteStatusTest: """Tests for certbot.compat.misc.execute_command_status.""" @classmethod diff --git a/certbot/tests/compat/os_test.py b/certbot/tests/compat/os_test.py index 673e50f9e..5bbc70fed 100644 --- a/certbot/tests/compat/os_test.py +++ b/certbot/tests/compat/os_test.py @@ -1,24 +1,21 @@ """Unit test for os module.""" import sys -import unittest import pytest from certbot.compat import os -class OsTest(unittest.TestCase): - """Unit tests for os module.""" - def test_forbidden_methods(self): - # Checks for os module - for method in ['chmod', 'chown', 'open', 'mkdir', 'makedirs', 'rename', - 'replace', 'access', 'stat', 'fstat']: - with pytest.raises(RuntimeError): - getattr(os, method)() - # Checks for os.path module - for method in ['realpath']: - with pytest.raises(RuntimeError): - getattr(os.path, method)() +def test_forbidden_methods(): + # Checks for os module + for method in ['chmod', 'chown', 'open', 'mkdir', 'makedirs', 'rename', + 'replace', 'access', 'stat', 'fstat']: + with pytest.raises(RuntimeError): + getattr(os, method)() + # Checks for os.path module + for method in ['realpath']: + with pytest.raises(RuntimeError): + getattr(os.path, method)() if __name__ == "__main__": diff --git a/certbot/tests/display/util_test.py b/certbot/tests/display/util_test.py index 4ae2d7c00..a055554a1 100644 --- a/certbot/tests/display/util_test.py +++ b/certbot/tests/display/util_test.py @@ -3,7 +3,6 @@ import io import socket import sys import tempfile -import unittest from unittest import mock import pytest @@ -12,89 +11,68 @@ from certbot import errors import certbot.tests.util as test_util -class NotifyTest(unittest.TestCase): - """Tests for certbot.display.util.notify""" - - @test_util.patch_display_util() - def test_notify(self, mock_util): - from certbot.display.util import notify - notify("Hello World") - mock_util().notification.assert_called_with( - "Hello World", pause=False, decorate=False, wrap=False - ) +@test_util.patch_display_util() +def test_notify(mock_util): + from certbot.display.util import notify + notify("Hello World") + mock_util().notification.assert_called_with( + "Hello World", pause=False, decorate=False, wrap=False + ) -class NotificationTest(unittest.TestCase): - """Tests for certbot.display.util.notification""" - - @test_util.patch_display_util() - def test_notification(self, mock_util): - from certbot.display.util import notification - notification("Hello World") - mock_util().notification.assert_called_with( - "Hello World", pause=True, decorate=True, wrap=True, force_interactive=False - ) +@test_util.patch_display_util() +def test_notification(mock_util): + from certbot.display.util import notification + notification("Hello World") + mock_util().notification.assert_called_with( + "Hello World", pause=True, decorate=True, wrap=True, force_interactive=False + ) -class MenuTest(unittest.TestCase): - """Tests for certbot.display.util.menu""" - - @test_util.patch_display_util() - def test_menu(self, mock_util): - from certbot.display.util import menu - menu("Hello World", ["one", "two"], default=0) - mock_util().menu.assert_called_with( - "Hello World", ["one", "two"], default=0, cli_flag=None, force_interactive=False - ) +@test_util.patch_display_util() +def test_menu(mock_util): + from certbot.display.util import menu + menu("Hello World", ["one", "two"], default=0) + mock_util().menu.assert_called_with( + "Hello World", ["one", "two"], default=0, cli_flag=None, force_interactive=False + ) -class InputTextTest(unittest.TestCase): - """Tests for certbot.display.util.input_text""" - - @test_util.patch_display_util() - def test_input_text(self, mock_util): - from certbot.display.util import input_text - input_text("Hello World", default="something") - mock_util().input.assert_called_with( - "Hello World", default='something', cli_flag=None, force_interactive=False - ) +@test_util.patch_display_util() +def test_input_text(mock_util): + from certbot.display.util import input_text + input_text("Hello World", default="something") + mock_util().input.assert_called_with( + "Hello World", default='something', cli_flag=None, force_interactive=False + ) -class YesNoTest(unittest.TestCase): - """Tests for certbot.display.util.yesno""" - - @test_util.patch_display_util() - def test_yesno(self, mock_util): - from certbot.display.util import yesno - yesno("Hello World", default=True) - mock_util().yesno.assert_called_with( - "Hello World", yes_label='Yes', no_label='No', default=True, cli_flag=None, - force_interactive=False - ) +@test_util.patch_display_util() +def test_yesno(mock_util): + from certbot.display.util import yesno + yesno("Hello World", default=True) + mock_util().yesno.assert_called_with( + "Hello World", yes_label='Yes', no_label='No', default=True, cli_flag=None, + force_interactive=False + ) -class ChecklistTest(unittest.TestCase): - """Tests for certbot.display.util.checklist""" - - @test_util.patch_display_util() - def test_checklist(self, mock_util): - from certbot.display.util import checklist - checklist("Hello World", ["one", "two"], default="one") - mock_util().checklist.assert_called_with( - "Hello World", ['one', 'two'], default='one', cli_flag=None, force_interactive=False - ) +@test_util.patch_display_util() +def test_checklist(mock_util): + from certbot.display.util import checklist + checklist("Hello World", ["one", "two"], default="one") + mock_util().checklist.assert_called_with( + "Hello World", ['one', 'two'], default='one', cli_flag=None, force_interactive=False + ) -class DirectorySelectTest(unittest.TestCase): - """Tests for certbot.display.util.directory_select""" - - @test_util.patch_display_util() - def test_directory_select(self, mock_util): - from certbot.display.util import directory_select - directory_select("Hello World", default="something") - mock_util().directory_select.assert_called_with( - "Hello World", default='something', cli_flag=None, force_interactive=False - ) +@test_util.patch_display_util() +def test_directory_select(mock_util): + from certbot.display.util import directory_select + directory_select("Hello World", default="something") + mock_util().directory_select.assert_called_with( + "Hello World", default='something', cli_flag=None, force_interactive=False + ) if __name__ == "__main__": diff --git a/certbot/tests/helpful_test.py b/certbot/tests/helpful_test.py index 6a9b5e73f..0c928d961 100644 --- a/certbot/tests/helpful_test.py +++ b/certbot/tests/helpful_test.py @@ -1,6 +1,5 @@ """Tests for certbot.helpful_parser""" import sys -import unittest from unittest import mock import pytest @@ -11,7 +10,7 @@ from certbot._internal.cli import _DomainsAction from certbot._internal.cli import HelpfulArgumentParser -class TestScanningFlags(unittest.TestCase): +class TestScanningFlags: '''Test the prescan_for_flag method of HelpfulArgumentParser''' def test_prescan_no_help_flag(self): arg_parser = HelpfulArgumentParser(['run'], {}) @@ -40,7 +39,7 @@ class TestScanningFlags(unittest.TestCase): arg_parser.help_topics) assert detected_flag is False -class TestDetermineVerbs(unittest.TestCase): +class TestDetermineVerbs: '''Tests for determine_verb methods of HelpfulArgumentParser''' def test_determine_verb_wrong_verb(self): arg_parser = HelpfulArgumentParser(['potato'], {}) @@ -71,7 +70,7 @@ class TestDetermineVerbs(unittest.TestCase): assert arg_parser.args == [] -class TestAdd(unittest.TestCase): +class TestAdd: '''Tests for add method in HelpfulArgumentParser''' def test_add_trivial_argument(self): arg_parser = HelpfulArgumentParser(['run'], {}) @@ -93,7 +92,7 @@ class TestAdd(unittest.TestCase): assert hasattr(parsed_args, 'eab_kid') -class TestAddGroup(unittest.TestCase): +class TestAddGroup: '''Test add_group method of HelpfulArgumentParser''' def test_add_group_no_input(self): arg_parser = HelpfulArgumentParser(['run'], {}) @@ -118,7 +117,7 @@ class TestAddGroup(unittest.TestCase): assert arg_parser.groups["certonly"] is False -class TestParseArgsErrors(unittest.TestCase): +class TestParseArgsErrors: '''Tests for errors that should be met for some cases in parse_args method in HelpfulArgumentParser''' def test_parse_args_renew_force_interactive(self): @@ -194,7 +193,7 @@ class TestParseArgsErrors(unittest.TestCase): arg_parser.parse_args() -class TestAddDeprecatedArgument(unittest.TestCase): +class TestAddDeprecatedArgument: """Tests for add_deprecated_argument method of HelpfulArgumentParser""" @mock.patch.object(HelpfulArgumentParser, "modify_kwargs_for_default_detection") diff --git a/certbot/tests/plugins/util_test.py b/certbot/tests/plugins/util_test.py index bf5817c10..c3d76f801 100644 --- a/certbot/tests/plugins/util_test.py +++ b/certbot/tests/plugins/util_test.py @@ -1,6 +1,5 @@ """Tests for certbot.plugins.util.""" import sys -import unittest from unittest import mock import pytest @@ -8,38 +7,33 @@ import pytest from certbot.compat import os -class GetPrefixTest(unittest.TestCase): - """Tests for certbot.plugins.get_prefixes.""" - def test_get_prefix(self): - from certbot.plugins.util import get_prefixes - assert get_prefixes('/a/b/c') == \ - [os.path.normpath(path) for path in ['/a/b/c', '/a/b', '/a', '/']] - assert get_prefixes('/') == [os.path.normpath('/')] - assert get_prefixes('a') == ['a'] +def test_get_prefix(): + from certbot.plugins.util import get_prefixes + assert get_prefixes('/a/b/c') == \ + [os.path.normpath(path) for path in ['/a/b/c', '/a/b', '/a', '/']] + assert get_prefixes('/') == [os.path.normpath('/')] + assert get_prefixes('a') == ['a'] -class PathSurgeryTest(unittest.TestCase): - """Tests for certbot.plugins.path_surgery.""" - - @mock.patch("certbot.plugins.util.logger.debug") - def test_path_surgery(self, mock_debug): - from certbot.plugins.util import path_surgery - all_path = {"PATH": "/usr/local/bin:/bin/:/usr/sbin/:/usr/local/sbin/"} - with mock.patch.dict('os.environ', all_path): - with mock.patch('certbot.util.exe_exists') as mock_exists: - mock_exists.return_value = True - assert path_surgery("eg") is True - assert mock_debug.call_count == 0 - assert os.environ["PATH"] == all_path["PATH"] - if os.name != 'nt': - # This part is specific to Linux since on Windows no PATH surgery is ever done. - no_path = {"PATH": "/tmp/"} - with mock.patch.dict('os.environ', no_path): - path_surgery("thingy") - assert mock_debug.call_count == (2 if os.name != 'nt' else 1) - assert "Failed to find" in mock_debug.call_args[0][0] - assert "/usr/local/bin" in os.environ["PATH"] - assert "/tmp" in os.environ["PATH"] +@mock.patch("certbot.plugins.util.logger.debug") +def test_path_surgery(mock_debug): + from certbot.plugins.util import path_surgery + all_path = {"PATH": "/usr/local/bin:/bin/:/usr/sbin/:/usr/local/sbin/"} + with mock.patch.dict('os.environ', all_path): + with mock.patch('certbot.util.exe_exists') as mock_exists: + mock_exists.return_value = True + assert path_surgery("eg") is True + assert mock_debug.call_count == 0 + assert os.environ["PATH"] == all_path["PATH"] + if os.name != 'nt': + # This part is specific to Linux since on Windows no PATH surgery is ever done. + no_path = {"PATH": "/tmp/"} + with mock.patch.dict('os.environ', no_path): + path_surgery("thingy") + assert mock_debug.call_count == (2 if os.name != 'nt' else 1) + assert "Failed to find" in mock_debug.call_args[0][0] + assert "/usr/local/bin" in os.environ["PATH"] + assert "/tmp" in os.environ["PATH"] if __name__ == "__main__": From 397f6bc20ae28ef666fa8fc63be3b144a881e8a3 Mon Sep 17 00:00:00 2001 From: alexzorin Date: Wed, 8 Mar 2023 00:40:39 +1100 Subject: [PATCH 57/57] docs: link for certbot-standalone-nfq plugin (#9607) --- certbot/docs/using.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/certbot/docs/using.rst b/certbot/docs/using.rst index 1ef649906..133bff8aa 100644 --- a/certbot/docs/using.rst +++ b/certbot/docs/using.rst @@ -323,6 +323,7 @@ Porkbun_ Y N DNS Authentication for Porkbun Infomaniak_ Y N DNS Authentication using Infomaniak Domains API dns-multi_ Y N DNS authentication of 100+ providers using go-acme/lego dns-dnsmanager_ Y N DNS Authentication for dnsmanager.io +standalone-nfq_ Y N HTTP Authentication that works with any webserver (Linux only) ================== ==== ==== =============================================================== .. _haproxy: https://github.com/greenhost/certbot-haproxy @@ -347,6 +348,7 @@ dns-dnsmanager_ Y N DNS Authentication for dnsmanager.io .. _Infomaniak: https://github.com/Infomaniak/certbot-dns-infomaniak .. _dns-multi: https://github.com/alexzorin/certbot-dns-multi .. _dns-dnsmanager: https://github.com/stayallive/certbot-dns-dnsmanager +.. _standalone-nfq: https://github.com/alexzorin/certbot-standalone-nfq If you're interested, you can also :ref:`write your own plugin `.