diff --git a/chatmaild/MANIFEST.in b/chatmaild/MANIFEST.in index a11a04f9..625d48a3 100644 --- a/chatmaild/MANIFEST.in +++ b/chatmaild/MANIFEST.in @@ -1,3 +1,4 @@ include src/chatmaild/*.f include src/chatmaild/ini/*.ini.f include src/chatmaild/ini/*.ini +include src/chatmaild/tests/mail-data/* diff --git a/chatmaild/pyproject.toml b/chatmaild/pyproject.toml index f0481a46..e87fc15b 100644 --- a/chatmaild/pyproject.toml +++ b/chatmaild/pyproject.toml @@ -20,6 +20,9 @@ where = ['src'] doveauth = "chatmaild.doveauth:main" filtermail = "chatmaild.filtermail:main" +[project.entry-points.pytest11] +"chatmaild.testplugin" = "chatmaild.tests.plugin" + [tool.pytest.ini_options] addopts = "-v -ra --strict-markers" log_format = "%(asctime)s %(levelname)s %(message)s" @@ -45,5 +48,5 @@ commands = [testenv] deps = pytest pdbpp -commands = pytest -v -rsXx {posargs: ../tests/chatmaild} +commands = pytest -v -rsXx {posargs} """ diff --git a/tests/mail-data/encrypted.eml b/chatmaild/src/chatmaild/tests/mail-data/encrypted.eml similarity index 100% rename from tests/mail-data/encrypted.eml rename to chatmaild/src/chatmaild/tests/mail-data/encrypted.eml diff --git a/tests/mail-data/fake-encrypted.eml b/chatmaild/src/chatmaild/tests/mail-data/fake-encrypted.eml similarity index 100% rename from tests/mail-data/fake-encrypted.eml rename to chatmaild/src/chatmaild/tests/mail-data/fake-encrypted.eml diff --git a/tests/mail-data/mdn.eml b/chatmaild/src/chatmaild/tests/mail-data/mdn.eml similarity index 100% rename from tests/mail-data/mdn.eml rename to chatmaild/src/chatmaild/tests/mail-data/mdn.eml diff --git a/tests/mail-data/plain.eml b/chatmaild/src/chatmaild/tests/mail-data/plain.eml similarity index 100% rename from tests/mail-data/plain.eml rename to chatmaild/src/chatmaild/tests/mail-data/plain.eml diff --git a/chatmaild/src/chatmaild/tests/plugin.py b/chatmaild/src/chatmaild/tests/plugin.py new file mode 100644 index 00000000..4a7e708a --- /dev/null +++ b/chatmaild/src/chatmaild/tests/plugin.py @@ -0,0 +1,68 @@ +import random +import importlib.resources +import itertools +from email.parser import BytesParser +from email import policy +import pytest + +from chatmaild.database import Database +from chatmaild.config import read_config, write_initial_config + + +@pytest.fixture +def make_config(tmp_path): + inipath = tmp_path.joinpath("chatmail.ini") + + def make_conf(mailname): + write_initial_config(inipath, mailname=mailname) + return read_config(inipath) + + return make_conf + + +@pytest.fixture +def example_config(make_config): + return make_config("chat.example.org") + + +@pytest.fixture +def maildomain(example_config): + return example_config.mailname + + +@pytest.fixture +def gencreds(maildomain): + count = itertools.count() + next(count) + + def gen(domain=None): + domain = domain if domain else maildomain + while 1: + num = next(count) + alphanumeric = "abcdefghijklmnopqrstuvwxyz1234567890" + user = "".join(random.choices(alphanumeric, k=10)) + user = f"ac{num}_{user}"[:9] + password = "".join(random.choices(alphanumeric, k=12)) + yield f"{user}@{domain}", f"{password}" + + return lambda domain=None: next(gen(domain)) + + +@pytest.fixture() +def db(tmpdir): + db_path = tmpdir / "passdb.sqlite" + print("database path:", db_path) + return Database(db_path) + + +@pytest.fixture +def maildata(request): + datadir = importlib.resources.files(__package__).joinpath("mail-data") + assert datadir.exists(), datadir + + def maildata(name, from_addr, to_addr): + data = datadir.joinpath(name).read_text() + text = data.format(from_addr=from_addr, to_addr=to_addr) + return BytesParser(policy=policy.default).parsebytes(text.encode()) + + return maildata diff --git a/tests/chatmaild/test_config.py b/chatmaild/src/chatmaild/tests/test_config.py similarity index 100% rename from tests/chatmaild/test_config.py rename to chatmaild/src/chatmaild/tests/test_config.py diff --git a/tests/chatmaild/test_doveauth.py b/chatmaild/src/chatmaild/tests/test_doveauth.py similarity index 96% rename from tests/chatmaild/test_doveauth.py rename to chatmaild/src/chatmaild/tests/test_doveauth.py index 07446861..23c0a1ab 100644 --- a/tests/chatmaild/test_doveauth.py +++ b/chatmaild/src/chatmaild/tests/test_doveauth.py @@ -59,8 +59,8 @@ def test_handle_dovecot_request(db): assert userdata["password"].startswith("{SHA512-CRYPT}") -def test_100_concurrent_lookups_different_accounts(db, gencreds): - num_threads = 100 +def test_50_concurrent_lookups_different_accounts(db, gencreds): + num_threads = 50 req_per_thread = 5 results = queue.Queue() diff --git a/tests/chatmaild/test_filtermail.py b/chatmaild/src/chatmaild/tests/test_filtermail.py similarity index 83% rename from tests/chatmaild/test_filtermail.py rename to chatmaild/src/chatmaild/tests/test_filtermail.py index 91f98a95..4db47d8d 100644 --- a/tests/chatmaild/test_filtermail.py +++ b/chatmaild/src/chatmaild/tests/test_filtermail.py @@ -26,27 +26,36 @@ def test_reject_forged_from(maildata, gencreds, handler): rcpt_tos = [gencreds()[0]] # test that the filter lets good mail through - env.content = maildata("plain.eml", from_addr=env.mail_from).as_bytes() + to_addr = gencreds()[0] + env.content = maildata( + "plain.eml", from_addr=env.mail_from, to_addr=to_addr + ).as_bytes() assert not handler.check_DATA(envelope=env) # test that the filter rejects forged mail - env.content = maildata("plain.eml", from_addr="forged@c3.testrun.org").as_bytes() + env.content = maildata( + "plain.eml", from_addr="forged@c3.testrun.org", to_addr=to_addr + ).as_bytes() error = handler.check_DATA(envelope=env) assert "500" in error def test_filtermail_no_encryption_detection(maildata): - msg = maildata("plain.eml") + msg = maildata( + "plain.eml", from_addr="some@example.org", to_addr="other@example.org" + ) assert not check_encrypted(msg) # https://xkcd.com/1181/ - msg = maildata("fake-encrypted.eml") + msg = maildata( + "fake-encrypted.eml", from_addr="some@example.org", to_addr="other@example.org" + ) assert not check_encrypted(msg) def test_filtermail_encryption_detection(maildata): - msg = maildata("encrypted.eml") + msg = maildata("encrypted.eml", from_addr="1@example.org", to_addr="2@example.org") assert check_encrypted(msg) # if the subject is not "..." it is not considered ac-encrypted diff --git a/tests/chatmaild/test_newmail.py b/chatmaild/src/chatmaild/tests/test_newmail.py similarity index 100% rename from tests/chatmaild/test_newmail.py rename to chatmaild/src/chatmaild/tests/test_newmail.py diff --git a/deploy-chatmail/pyproject.toml b/deploy-chatmail/pyproject.toml index 39eed1d8..f480bec1 100644 --- a/deploy-chatmail/pyproject.toml +++ b/deploy-chatmail/pyproject.toml @@ -20,6 +20,9 @@ dependencies = [ [project.scripts] cmdeploy = "deploy_chatmail.cmdeploy:main" +[project.entry-points.pytest11] +"chatmaild.testplugin" = "chatmaild.tests.plugin" + [tool.pytest.ini_options] addopts = "-v -ra --strict-markers" diff --git a/tests/conftest.py b/tests/conftest.py index 4bef976d..d3a4e970 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -352,22 +352,6 @@ def lp(request): return LP() -@pytest.fixture -def maildata(request, gencreds): - datadir = conftestdir.joinpath("mail-data") - - def maildata(name, from_addr=None, to_addr=None): - if from_addr is None: - from_addr = gencreds()[0] - if to_addr is None: - to_addr = gencreds()[0] - data = datadir.joinpath(name).read_text() - text = data.format(from_addr=from_addr, to_addr=to_addr) - return BytesParser(policy=policy.default).parsebytes(text.encode()) - - return maildata - - @pytest.fixture def cmsetup(maildomain, gencreds): return CMSetup(maildomain, gencreds) @@ -414,16 +398,3 @@ class CMUser: imap.login(self.addr, self.password) self._imap = imap return self._imap - - -@pytest.fixture -def make_config(tmp_path): - from chatmaild.config import read_config, write_initial_config - - inipath = tmp_path.joinpath("chatmail.ini") - - def make_conf(mailname): - write_initial_config(inipath, mailname=mailname) - return read_config(inipath) - - return make_conf diff --git a/tests/online/test_1_basic.py b/tests/online/test_1_basic.py index 31e877ad..a6705da5 100644 --- a/tests/online/test_1_basic.py +++ b/tests/online/test_1_basic.py @@ -20,7 +20,7 @@ def test_use_two_chatmailservers(cmfactory, maildomain2): @pytest.mark.parametrize("forgeaddr", ["internal", "someone@example.org"]) -def test_reject_forged_from(cmsetup, maildata, lp, forgeaddr): +def test_reject_forged_from(cmsetup, maildata, gencreds, lp, forgeaddr): user1, user3 = cmsetup.gen_users(2) lp.sec("send encrypted message with forged from") diff --git a/tests/test_cmdeploy.py b/tests/test_cmdeploy.py index cad55bdd..c38fb930 100644 --- a/tests/test_cmdeploy.py +++ b/tests/test_cmdeploy.py @@ -24,7 +24,7 @@ class TestCmdline: def test_init(self, tmp_path): main(["init", "chat.example.org"]) inipath = tmp_path.joinpath("chatmail.ini") - config = read_config(inipath.strpath) + config = read_config(inipath) assert config.mailname == "chat.example.org" def test_init_not_overwrite(self):