Compare commits

...

9 Commits

Author SHA1 Message Date
holger krekel
cbbcf3cbca add marker dynamically to allow "pytest" to execute nicely at repo root without warnings 2023-10-20 22:45:11 +02:00
holger krekel
d2af9df8f9 rename test files to be unambigously numbered 2023-10-20 22:39:23 +02:00
holger krekel
83e6a42252 slight refinement for benchmark formatting, not worth a PR 2023-10-20 18:43:06 +02:00
link2xt
eb69dd58f7 Setup CI 2023-10-20 15:18:17 +02:00
link2xt
31c45f951d dictproxy: use crypt instead of doveadm pw 2023-10-20 14:05:25 +02:00
holger krekel
3012bfb79d some reformatting and striking overall 2023-10-20 11:05:58 +02:00
holger krekel
03442bc115 some improvements, adding a bnech 2023-10-20 11:05:58 +02:00
holger krekel
1ae6291d06 add ping-pong bench and formatting 2023-10-20 11:05:58 +02:00
holger krekel
1b347f97a0 better benchmarking and reporting 2023-10-20 11:05:58 +02:00
9 changed files with 127 additions and 41 deletions

18
.github/workflows/ci.yaml vendored Normal file
View File

@@ -0,0 +1,18 @@
name: CI
on:
pull_request:
push:
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Lint chatmaild
working-directory: chatmaild
run: pipx run tox
- name: Lint deploy-chatmail
working-directory: deploy-chatmail
run: pipx run tox

View File

@@ -2,13 +2,13 @@ import logging
import os
import sys
import json
import crypt
from socketserver import (
UnixStreamServer,
StreamRequestHandler,
ThreadingMixIn,
)
import pwd
import subprocess
from .database import Database
@@ -16,17 +16,9 @@ NOCREATE_FILE = "/etc/chatmail-nocreate"
def encrypt_password(password: str):
password = password.encode("ascii")
# https://doc.dovecot.org/configuration_manual/authentication/password_schemes/
process = subprocess.Popen(
["doveadm", "pw", "-s", "SHA512-CRYPT"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
)
stdout_data, _stderr_data = process.communicate(
input=password + b"\n" + password + b"\n"
)
return stdout_data.decode("ascii").strip()
passhash = crypt.crypt(password, crypt.METHOD_SHA512)
return "{SHA512-CRYPT}" + passhash
def create_user(db, user, password):

View File

@@ -1,6 +1,6 @@
import importlib.resources
from pyinfra.operations import apt, files, systemd, server
from pyinfra.operations import apt, files, server
def deploy_acmetool(nginx_hook=False, email="", domains=[]):

View File

@@ -1,34 +1,60 @@
def test_tls_serialized_connect(benchmark, imap_or_smtp):
def connect():
imap_or_smtp.connect()
def test_tls_imap(benchmark, imap):
def imap_connect():
imap.connect()
benchmark(connect)
benchmark(imap_connect, 10)
def test_login(benchmark, imap_or_smtp, gencreds):
cls = imap_or_smtp.__class__
conns = []
for i in range(20):
conn = cls(imap_or_smtp.host)
conn.connect()
conns.append(conn)
def test_login_imap(benchmark, imap, gencreds):
def imap_connect_and_login():
imap.connect()
imap.login(*gencreds())
def login():
conn = conns.pop()
conn.login(*gencreds())
benchmark(login)
benchmark(imap_connect_and_login, 10)
def test_send_and_receive_10(benchmark, cmfactory, lp):
"""send many messages between two accounts"""
ac1, ac2 = cmfactory.get_online_accounts(2)
chat = cmfactory.get_accepted_chat(ac1, ac2)
def test_tls_smtp(benchmark, smtp):
def smtp_connect():
smtp.connect()
def send_10_receive_all():
for i in range(10):
chat.send_text(f"hello {i}")
for i in range(10):
ac2.wait_next_incoming_message()
benchmark(smtp_connect, 10)
benchmark(send_10_receive_all)
def test_login_smtp(benchmark, smtp, gencreds):
def smtp_connect_and_login():
smtp.connect()
smtp.login(*gencreds())
benchmark(smtp_connect_and_login, 10)
class TestDC:
def test_autoconfigure(self, benchmark, cmfactory):
def autoconfig_and_idle_ready():
cmfactory.get_online_accounts(1)
benchmark(autoconfig_and_idle_ready, 5)
def test_ping_pong(self, benchmark, cmfactory):
ac1, ac2 = cmfactory.get_online_accounts(2)
chat = cmfactory.get_accepted_chat(ac1, ac2)
def ping_pong():
chat.send_text("ping")
msg = ac2.wait_next_incoming_message()
msg.chat.send_text("pong")
ac1.wait_next_incoming_message()
benchmark(ping_pong, 5)
def test_send_10_receive_10(self, benchmark, cmfactory, lp):
ac1, ac2 = cmfactory.get_online_accounts(2)
chat = cmfactory.get_accepted_chat(ac1, ac2)
def send_10_receive_10():
for i in range(10):
chat.send_text(f"hello {i}")
for i in range(10):
ac2.wait_next_incoming_message()
benchmark(send_10_receive_10, 5)

View File

@@ -1,10 +1,12 @@
import os
import io
import time
import random
import subprocess
import imaplib
import smtplib
import itertools
from math import ceil
import pytest
@@ -14,6 +16,13 @@ def pytest_addoption(parser):
)
def pytest_configure(config):
config._benchresults = {}
config.addinivalue_line(
"markers", "slow: mark test to require --slow option to run"
)
def pytest_runtest_setup(item):
markers = list(item.iter_markers(name="slow"))
if markers:
@@ -54,6 +63,49 @@ def pytest_report_header():
return ["-" * len(text), text, "-" * len(text)]
@pytest.fixture
def benchmark(request):
def bench(func, num, name=None):
if name is None:
name = func.__name__
durations = []
for i in range(num):
now = time.time()
func()
durations.append(time.time() - now)
durations.sort()
request.config._benchresults[name] = durations
return bench
def pytest_terminal_summary(terminalreporter):
tr = terminalreporter
results = tr.config._benchresults
if not results:
return
tr.section("benchmark results")
float_names = 'median min max'.split()
width = max(map(len, float_names))
def fcol(parts):
return " ".join(part.rjust(width) for part in parts)
headers = f"{'benchmark name': <30} " + fcol(float_names)
tr.write_line(headers)
tr.write_line("-" * len(headers))
for name, durations in results.items():
measures = [
sorted(durations)[len(durations) // 2],
min(durations),
max(durations),
]
line = f"{name: <30} "
line += fcol(f"{float: 2.2f}" for float in measures)
tr.write_line(line)
@pytest.fixture
def imap(maildomain):
return ImapConn(maildomain)

View File

@@ -1,3 +1,2 @@
[pytest]
addopts = -vrsx --strict-markers
markers = slow: mark test as slow (requires --slow option to run)

View File

@@ -6,9 +6,8 @@ deploy-chatmail/venv/bin/pip install -e deploy-chatmail
deploy-chatmail/venv/bin/pip install -e chatmaild
python3 -m venv chatmaild/venv
sudo apt install -y dovecot-core && sudo systemctl disable --now dovecot
chatmaild/venv/bin/pip install --upgrade pytest build 'setuptools>=68'
chatmaild/venv/bin/pip install -e chatmaild
python3 -m venv online-tests/venv
online-tests/venv/bin/pip install pytest pytest-timeout pdbpp deltachat pytest-benchmark
online-tests/venv/bin/pip install pytest pytest-timeout pdbpp deltachat