simplify and speedup configuration handling

refactor conftest.py away
This commit is contained in:
holger krekel
2020-05-20 21:13:03 +02:00
parent fedc946886
commit ad522cd798
6 changed files with 83 additions and 100 deletions

View File

@@ -543,6 +543,10 @@ class Account(object):
self._pm.check_pending() self._pm.check_pending()
return plugin return plugin
def remove_account_plugin(self, plugin, name=None):
""" remove an account plugin. """
self._pm.unregister(plugin, name=name)
@contextmanager @contextmanager
def temp_plugin(self, plugin): def temp_plugin(self, plugin):
""" run a with-block with the given plugin temporarily registered. """ """ run a with-block with the given plugin temporarily registered. """
@@ -569,22 +573,27 @@ class Account(object):
:returns: None (account is configured and with io-scheduling running) :returns: None (account is configured and with io-scheduling running)
""" """
if not self.is_configured(): if not self.is_configured():
if not self.get_config("addr") or not self.get_config("mail_pw"): self.configure()
raise MissingCredentials("addr or mail_pwd not set in config") self.wait_configure_finish()
with self.temp_plugin(ConfigureTracker()) as config_tracker:
lib.dc_configure(self._dc_context)
config_tracker.wait_finish()
lib.dc_context_run(self._dc_context) lib.dc_context_run(self._dc_context)
@contextmanager
def configure(self): def configure(self):
if self.is_configured(): assert not self.is_configured()
return assert not hasattr(self, "_configtracker")
if not self.get_config("addr") or not self.get_config("mail_pw"): if not self.get_config("addr") or not self.get_config("mail_pw"):
raise MissingCredentials("addr or mail_pwd not set in config") raise MissingCredentials("addr or mail_pwd not set in config")
with self.temp_plugin(ConfigureTracker()) as config_tracker: if hasattr(self, "_configtracker"):
lib.dc_configure(self._dc_context) self.remove_account_plugin(self._configtracker)
yield config_tracker self._configtracker = ConfigureTracker()
self.add_account_plugin(self._configtracker)
lib.dc_configure(self._dc_context)
def wait_configure_finish(self):
try:
self._configtracker.wait_finish()
finally:
self.remove_account_plugin(self._configtracker)
del self._configtracker
def is_started(self): def is_started(self):
return self._event_thread.is_alive() and bool(lib.dc_is_running(self._dc_context)) return self._event_thread.is_alive() and bool(lib.dc_is_running(self._dc_context))

View File

@@ -90,6 +90,13 @@ class FFIEventTracker:
else: else:
assert not rex.match(ev.name), "event found {}".format(ev) assert not rex.match(ev.name), "event found {}".format(ev)
def wait_securejoin_inviter_progress(self, target):
while 1:
event = self.get_matching("DC_EVENT_SECUREJOIN_INVITER_PROGRESS")
if event.data2 >= target:
print("** SECUREJOINT-INVITER PROGRESS {}".format(target), self.account)
break
def get_matching(self, event_name_regex, check_error=True, timeout=None): def get_matching(self, event_name_regex, check_error=True, timeout=None):
self.account.log("-- waiting for event with regex: {} --".format(event_name_regex)) self.account.log("-- waiting for event with regex: {} --".format(event_name_regex))
rex = re.compile("(?:{}).*".format(event_name_regex)) rex = re.compile("(?:{}).*".format(event_name_regex))

View File

@@ -13,7 +13,6 @@ import pytest
import requests import requests
from . import Account, const from . import Account, const
from .tracker import ConfigureTracker
from .capi import lib from .capi import lib
from .events import FFIEventLogger, FFIEventTracker from .events import FFIEventLogger, FFIEventTracker
from _pytest.monkeypatch import MonkeyPatch from _pytest.monkeypatch import MonkeyPatch
@@ -234,7 +233,6 @@ def acfactory(pytestconfig, tmpdir, request, session_liveconfig, data):
def make_account(self, path, logid, quiet=False): def make_account(self, path, logid, quiet=False):
ac = Account(path, logging=self._logging) ac = Account(path, logging=self._logging)
ac._evtracker = ac.add_account_plugin(FFIEventTracker(ac)) ac._evtracker = ac.add_account_plugin(FFIEventTracker(ac))
ac._configtracker = ac.add_account_plugin(ConfigureTracker())
if not quiet: if not quiet:
ac.add_account_plugin(FFIEventLogger(ac, logid=logid)) ac.add_account_plugin(FFIEventLogger(ac, logid=logid))
self._accounts.append(ac) self._accounts.append(ac)
@@ -297,7 +295,7 @@ def acfactory(pytestconfig, tmpdir, request, session_liveconfig, data):
return ac, dict(configdict) return ac, dict(configdict)
def get_online_configuring_account(self, mvbox=False, sentbox=False, move=False, def get_online_configuring_account(self, mvbox=False, sentbox=False, move=False,
pre_generated_key=True, quiet=False, config={}, start=True): pre_generated_key=True, quiet=False, config={}):
ac, configdict = self.get_online_config( ac, configdict = self.get_online_config(
pre_generated_key=pre_generated_key, quiet=quiet) pre_generated_key=pre_generated_key, quiet=quiet)
configdict.update(config) configdict.update(config)
@@ -305,23 +303,20 @@ def acfactory(pytestconfig, tmpdir, request, session_liveconfig, data):
configdict["mvbox_move"] = str(int(move)) configdict["mvbox_move"] = str(int(move))
configdict["sentbox_watch"] = str(int(sentbox)) configdict["sentbox_watch"] = str(int(sentbox))
ac.update_config(configdict) ac.update_config(configdict)
if start: ac.configure()
ac.start()
return ac return ac
def get_one_online_account(self, pre_generated_key=True, mvbox=False, move=False): def get_one_online_account(self, pre_generated_key=True, mvbox=False, move=False):
ac1 = self.get_online_configuring_account( ac1 = self.get_online_configuring_account(
pre_generated_key=pre_generated_key, mvbox=mvbox, move=move) pre_generated_key=pre_generated_key, mvbox=mvbox, move=move)
ac1._configtracker.wait_imap_connected() ac1.wait_configure_finish()
ac1._configtracker.wait_smtp_connected()
ac1._configtracker.wait_finish()
return ac1 return ac1
def get_two_online_accounts(self, move=False, quiet=False): def get_two_online_accounts(self, move=False, quiet=False):
ac1 = self.get_online_configuring_account(move=True, quiet=quiet) ac1 = self.get_online_configuring_account(move=True, quiet=quiet)
ac2 = self.get_online_configuring_account(quiet=quiet) ac2 = self.get_online_configuring_account(quiet=quiet)
ac1._configtracker.wait_finish() ac1.wait_configure_finish()
ac2._configtracker.wait_finish() ac2.wait_configure_finish()
return ac1, ac2 return ac1, ac2
def clone_online_account(self, account, pre_generated_key=True): def clone_online_account(self, account, pre_generated_key=True):
@@ -339,7 +334,7 @@ def acfactory(pytestconfig, tmpdir, request, session_liveconfig, data):
mvbox_move=account.get_config("mvbox_move"), mvbox_move=account.get_config("mvbox_move"),
sentbox_watch=account.get_config("sentbox_watch"), sentbox_watch=account.get_config("sentbox_watch"),
)) ))
ac.start() ac.configure()
return ac return ac
def run_bot_process(self, module, ffi=True): def run_bot_process(self, module, ffi=True):

View File

@@ -1,18 +0,0 @@
from __future__ import print_function
def wait_configuration_progress(account, min_target, max_target=1001, check_error=True):
min_target = min(min_target, max_target)
while 1:
event = account._evtracker.get_matching("DC_EVENT_CONFIGURE_PROGRESS")
if event.data1 >= min_target and event.data1 <= max_target:
print("** CONFIG PROGRESS {}".format(min_target), account)
break
def wait_securejoin_inviter_progress(account, target):
while 1:
event = account._evtracker.get_matching("DC_EVENT_SECUREJOIN_INVITER_PROGRESS")
if event.data2 >= target:
print("** SECUREJOINT-INVITER PROGRESS {}".format(target), account)
break

View File

@@ -3,13 +3,10 @@ import pytest
import os import os
import queue import queue
import time import time
from deltachat import const, Account, capi from deltachat import const, Account
from deltachat.message import Message from deltachat.message import Message
from deltachat.hookspec import account_hookimpl from deltachat.hookspec import account_hookimpl
from deltachat.tracker import ConfigureTracker
from datetime import datetime, timedelta from datetime import datetime, timedelta
from conftest import (wait_configuration_progress,
wait_securejoin_inviter_progress)
@pytest.mark.parametrize("msgtext,res", [ @pytest.mark.parametrize("msgtext,res", [
@@ -535,8 +532,8 @@ class TestOnlineAccount:
) )
# rsa key gen can be slow especially on CI, adjust timeout # rsa key gen can be slow especially on CI, adjust timeout
ac1._evtracker.set_timeout(120) ac1._evtracker.set_timeout(120)
wait_configuration_progress(ac1, 1000) ac1.wait_configure_finish()
wait_configuration_progress(ac2, 1000) ac2.wait_configure_finish()
chat = self.get_chat(ac1, ac2, both_created=True) chat = self.get_chat(ac1, ac2, both_created=True)
lp.sec("ac1: send unencrypted message to ac2") lp.sec("ac1: send unencrypted message to ac2")
@@ -564,12 +561,13 @@ class TestOnlineAccount:
assert msg3_in.is_encrypted() assert msg3_in.is_encrypted()
def test_configure_canceled(self, acfactory): def test_configure_canceled(self, acfactory):
ac1 = acfactory.get_online_configuring_account(start=False) ac1 = acfactory.get_online_configuring_account()
with ac1.temp_plugin(ConfigureTracker()) as config_tracker: ac1._configtracker.wait_progress()
capi.lib.dc_configure(ac1._dc_context) ac1.stop_ongoing()
config_tracker.wait_progress() try:
ac1.stop_ongoing() ac1.wait_configure_finish()
config_tracker.wait_finish() except ac1._configtracker.ConfigureFailed:
pass
def test_export_import_self_keys(self, acfactory, tmpdir): def test_export_import_self_keys(self, acfactory, tmpdir):
ac1, ac2 = acfactory.get_two_online_accounts() ac1, ac2 = acfactory.get_two_online_accounts()
@@ -590,9 +588,9 @@ class TestOnlineAccount:
# are copied to it via BCC. # are copied to it via BCC.
ac1_clone = acfactory.clone_online_account(ac1) ac1_clone = acfactory.clone_online_account(ac1)
wait_configuration_progress(ac1, 1000) ac1.wait_configure_finish()
wait_configuration_progress(ac2, 1000) ac2.wait_configure_finish()
wait_configuration_progress(ac1_clone, 1000) ac1_clone.wait_configure_finish()
chat = self.get_chat(ac1, ac2) chat = self.get_chat(ac1, ac2)
@@ -696,10 +694,10 @@ class TestOnlineAccount:
ac2 = acfactory.get_online_configuring_account() ac2 = acfactory.get_online_configuring_account()
lp.sec("ac2: waiting for configuration") lp.sec("ac2: waiting for configuration")
wait_configuration_progress(ac2, 1000) ac2.wait_configure_finish()
lp.sec("ac1: waiting for configuration") lp.sec("ac1: waiting for configuration")
wait_configuration_progress(ac1, 1000) ac1.wait_configure_finish()
lp.sec("ac1: send message and wait for ac2 to receive it") lp.sec("ac1: send message and wait for ac2 to receive it")
chat = self.get_chat(ac1, ac2) chat = self.get_chat(ac1, ac2)
@@ -711,8 +709,8 @@ class TestOnlineAccount:
def test_move_works(self, acfactory): def test_move_works(self, acfactory):
ac1 = acfactory.get_online_configuring_account() ac1 = acfactory.get_online_configuring_account()
ac2 = acfactory.get_online_configuring_account(mvbox=True, move=True) ac2 = acfactory.get_online_configuring_account(mvbox=True, move=True)
wait_configuration_progress(ac2, 1000) ac2.wait_configure_finish()
wait_configuration_progress(ac1, 1000) ac1.wait_configure_finish()
chat = self.get_chat(ac1, ac2) chat = self.get_chat(ac1, ac2)
chat.send_text("message1") chat.send_text("message1")
ev = ac2._evtracker.get_matching("DC_EVENT_INCOMING_MSG|DC_EVENT_MSGS_CHANGED") ev = ac2._evtracker.get_matching("DC_EVENT_INCOMING_MSG|DC_EVENT_MSGS_CHANGED")
@@ -723,8 +721,8 @@ class TestOnlineAccount:
ac1 = acfactory.get_online_configuring_account(mvbox=True, move=True) ac1 = acfactory.get_online_configuring_account(mvbox=True, move=True)
ac1.set_config("bcc_self", "1") ac1.set_config("bcc_self", "1")
ac2 = acfactory.get_online_configuring_account() ac2 = acfactory.get_online_configuring_account()
wait_configuration_progress(ac2, 1000) ac2.wait_configure_finish()
wait_configuration_progress(ac1, 1000) ac1.wait_configure_finish()
chat = self.get_chat(ac1, ac2) chat = self.get_chat(ac1, ac2)
chat.send_text("message1") chat.send_text("message1")
chat.send_text("message2") chat.send_text("message2")
@@ -1102,8 +1100,7 @@ class TestOnlineAccount:
assert m == msg_in assert m == msg_in
def test_import_export_online_all(self, acfactory, tmpdir, lp): def test_import_export_online_all(self, acfactory, tmpdir, lp):
ac1 = acfactory.get_online_configuring_account() ac1 = acfactory.get_one_online_account()
wait_configuration_progress(ac1, 1000)
lp.sec("create some chat content") lp.sec("create some chat content")
contact1 = ac1.create_contact("some1@hello.com", name="some1") contact1 = ac1.create_contact("some1@hello.com", name="some1")
@@ -1151,8 +1148,8 @@ class TestOnlineAccount:
# as of Jul2019 # as of Jul2019
ac1 = acfactory.get_online_configuring_account() ac1 = acfactory.get_online_configuring_account()
ac2 = acfactory.clone_online_account(ac1) ac2 = acfactory.clone_online_account(ac1)
wait_configuration_progress(ac2, 1000) ac2.wait_configure_finish()
wait_configuration_progress(ac1, 1000) ac1.wait_configure_finish()
lp.sec("trigger ac setup message and return setupcode") lp.sec("trigger ac setup message and return setupcode")
assert ac1.get_info()["fingerprint"] != ac2.get_info()["fingerprint"] assert ac1.get_info()["fingerprint"] != ac2.get_info()["fingerprint"]
@@ -1175,8 +1172,8 @@ class TestOnlineAccount:
ac1 = acfactory.get_online_configuring_account() ac1 = acfactory.get_online_configuring_account()
ac2 = acfactory.clone_online_account(ac1) ac2 = acfactory.clone_online_account(ac1)
ac2._evtracker.set_timeout(30) ac2._evtracker.set_timeout(30)
wait_configuration_progress(ac2, 1000) ac2.wait_configure_finish()
wait_configuration_progress(ac1, 1000) ac1.wait_configure_finish()
lp.sec("trigger ac setup message but ignore") lp.sec("trigger ac setup message but ignore")
assert ac1.get_info()["fingerprint"] != ac2.get_info()["fingerprint"] assert ac1.get_info()["fingerprint"] != ac2.get_info()["fingerprint"]
@@ -1202,7 +1199,7 @@ class TestOnlineAccount:
lp.sec("ac2: start QR-code based setup contact protocol") lp.sec("ac2: start QR-code based setup contact protocol")
ch = ac2.qr_setup_contact(qr) ch = ac2.qr_setup_contact(qr)
assert ch.id >= 10 assert ch.id >= 10
wait_securejoin_inviter_progress(ac1, 1000) ac1._evtracker.wait_securejoin_inviter_progress(1000)
def test_qr_join_chat(self, acfactory, lp): def test_qr_join_chat(self, acfactory, lp):
ac1, ac2 = acfactory.get_two_online_accounts() ac1, ac2 = acfactory.get_two_online_accounts()
@@ -1216,7 +1213,7 @@ class TestOnlineAccount:
# check that at least some of the handshake messages are deleted # check that at least some of the handshake messages are deleted
ac1._evtracker.get_matching("DC_EVENT_IMAP_MESSAGE_DELETED") ac1._evtracker.get_matching("DC_EVENT_IMAP_MESSAGE_DELETED")
ac2._evtracker.get_matching("DC_EVENT_IMAP_MESSAGE_DELETED") ac2._evtracker.get_matching("DC_EVENT_IMAP_MESSAGE_DELETED")
wait_securejoin_inviter_progress(ac1, 1000) ac1._evtracker.wait_securejoin_inviter_progress(1000)
def test_qr_verified_group_and_chatting(self, acfactory, lp): def test_qr_verified_group_and_chatting(self, acfactory, lp):
ac1, ac2 = acfactory.get_two_online_accounts() ac1, ac2 = acfactory.get_two_online_accounts()
@@ -1227,7 +1224,7 @@ class TestOnlineAccount:
lp.sec("ac2: start QR-code based join-group protocol") lp.sec("ac2: start QR-code based join-group protocol")
chat2 = ac2.qr_join_chat(qr) chat2 = ac2.qr_join_chat(qr)
assert chat2.id >= 10 assert chat2.id >= 10
wait_securejoin_inviter_progress(ac1, 1000) ac1._evtracker.wait_securejoin_inviter_progress(1000)
lp.sec("ac2: read member added message") lp.sec("ac2: read member added message")
msg = ac2._evtracker.wait_next_incoming_message() msg = ac2._evtracker.wait_next_incoming_message()
@@ -1487,7 +1484,7 @@ class TestGroupStressTests:
lp.sec("creating and configuring five accounts") lp.sec("creating and configuring five accounts")
accounts = [acfactory.get_online_configuring_account() for i in range(5)] accounts = [acfactory.get_online_configuring_account() for i in range(5)]
for acc in accounts: for acc in accounts:
wait_configuration_progress(acc, 1000) acc.wait_configure_finish()
ac1 = accounts.pop() ac1 = accounts.pop()
lp.sec("ac1: setting up contacts with 4 other members") lp.sec("ac1: setting up contacts with 4 other members")
@@ -1591,7 +1588,7 @@ class TestGroupStressTests:
lp.sec("creating and configuring five accounts") lp.sec("creating and configuring five accounts")
accounts = [acfactory.get_online_configuring_account() for i in range(3)] accounts = [acfactory.get_online_configuring_account() for i in range(3)]
for acc in accounts: for acc in accounts:
wait_configuration_progress(acc, 1000) acc.wait_configure_finish()
ac1 = accounts.pop() ac1 = accounts.pop()
lp.sec("ac1: setting up contacts with 2 other members") lp.sec("ac1: setting up contacts with 2 other members")
@@ -1660,27 +1657,26 @@ class TestOnlineConfigureFails:
ac1, configdict = acfactory.get_online_config() ac1, configdict = acfactory.get_online_config()
ac1.update_config(dict(addr=configdict["addr"], mail_pw="123")) ac1.update_config(dict(addr=configdict["addr"], mail_pw="123"))
with ac1.configure() as tracker: ac1.configure()
tracker.wait_progress(500) ac1._configtracker.wait_progress(500)
tracker.wait_progress(0) ac1._configtracker.wait_progress(0)
ev = ac1._evtracker.get_matching("DC_EVENT_ERROR_NETWORK") ev = ac1._evtracker.get_matching("DC_EVENT_ERROR_NETWORK")
assert "cannot login" in ev.data2.lower() assert "cannot login" in ev.data2.lower()
def test_invalid_user(self, acfactory): def test_invalid_user(self, acfactory):
ac1, configdict = acfactory.get_online_config() ac1, configdict = acfactory.get_online_config()
ac1.update_config(dict(addr="x" + configdict["addr"], mail_pw=configdict["mail_pw"])) ac1.update_config(dict(addr="x" + configdict["addr"], mail_pw=configdict["mail_pw"]))
with ac1.configure() as tracker: ac1.configure()
tracker.wait_progress(500) ac1._configtracker.wait_progress(500)
tracker.wait_progress(0) ac1._configtracker.wait_progress(0)
ev = ac1._evtracker.get_matching("DC_EVENT_ERROR_NETWORK") ev = ac1._evtracker.get_matching("DC_EVENT_ERROR_NETWORK")
assert "cannot login" in ev.data2.lower() assert "cannot login" in ev.data2.lower()
def test_invalid_domain(self, acfactory): def test_invalid_domain(self, acfactory):
ac1, configdict = acfactory.get_online_config() ac1, configdict = acfactory.get_online_config()
ac1.update_config((dict(addr=configdict["addr"] + "x", mail_pw=configdict["mail_pw"]))) ac1.update_config((dict(addr=configdict["addr"] + "x", mail_pw=configdict["mail_pw"])))
with ac1.configure() as tracker: ac1.configure()
tracker.wait_progress(500) ac1._configtracker.wait_progress(500)
tracker.wait_progress(0) ac1._configtracker.wait_progress(0)
wait_configuration_progress(ac1, 500)
ev = ac1._evtracker.get_matching("DC_EVENT_ERROR_NETWORK") ev = ac1._evtracker.get_matching("DC_EVENT_ERROR_NETWORK")
assert "could not connect" in ev.data2.lower() assert "could not connect" in ev.data2.lower()

View File

@@ -6,24 +6,24 @@ import shutil
import pytest import pytest
from filecmp import cmp from filecmp import cmp
from conftest import wait_configuration_progress
from deltachat import const from deltachat import const
def wait_msgs_changed(account, chat_id, msg_id=None): def wait_msgs_changed(account, chat_id, msg_id=None):
ev = account._evtracker.get_matching("DC_EVENT_MSGS_CHANGED") account.log("waiting for chat_id={} msg_id={}".format(chat_id, msg_id))
assert ev.data1 == chat_id while 1:
if msg_id is not None: ev = account._evtracker.get_matching("DC_EVENT_MSGS_CHANGED")
assert ev.data2 == msg_id if ev.data1 != chat_id:
return ev.data2 account.log("waiting got mismatched DC_EVENT_MSGS_CHANGED")
continue
if msg_id is not None:
assert ev.data2 == msg_id
return ev.data2
class TestOnlineInCreation: class TestOnlineInCreation:
def test_increation_not_blobdir(self, tmpdir, acfactory, lp): def test_increation_not_blobdir(self, tmpdir, acfactory, lp):
ac1 = acfactory.get_online_configuring_account() ac1, ac2 = acfactory.get_two_online_accounts()
ac2 = acfactory.get_online_configuring_account()
wait_configuration_progress(ac1, 1000)
wait_configuration_progress(ac2, 1000)
c2 = ac1.create_contact(email=ac2.get_config("addr")) c2 = ac1.create_contact(email=ac2.get_config("addr"))
chat = ac1.create_chat_by_contact(c2) chat = ac1.create_chat_by_contact(c2)
@@ -35,10 +35,7 @@ class TestOnlineInCreation:
chat.prepare_message_file(src.strpath) chat.prepare_message_file(src.strpath)
def test_no_increation_copies_to_blobdir(self, tmpdir, acfactory, lp): def test_no_increation_copies_to_blobdir(self, tmpdir, acfactory, lp):
ac1 = acfactory.get_online_configuring_account() ac1, ac2 = acfactory.get_two_online_accounts()
ac2 = acfactory.get_online_configuring_account()
wait_configuration_progress(ac1, 1000)
wait_configuration_progress(ac2, 1000)
c2 = ac1.create_contact(email=ac2.get_config("addr")) c2 = ac1.create_contact(email=ac2.get_config("addr"))
chat = ac1.create_chat_by_contact(c2) chat = ac1.create_chat_by_contact(c2)
@@ -53,10 +50,7 @@ class TestOnlineInCreation:
assert os.path.exists(blob_src), "file.txt not copied to blobdir" assert os.path.exists(blob_src), "file.txt not copied to blobdir"
def test_forward_increation(self, acfactory, data, lp): def test_forward_increation(self, acfactory, data, lp):
ac1 = acfactory.get_online_configuring_account() ac1, ac2 = acfactory.get_two_online_accounts()
ac2 = acfactory.get_online_configuring_account()
wait_configuration_progress(ac1, 1000)
wait_configuration_progress(ac2, 1000)
c2 = ac1.create_contact(email=ac2.get_config("addr")) c2 = ac1.create_contact(email=ac2.get_config("addr"))
chat = ac1.create_chat_by_contact(c2) chat = ac1.create_chat_by_contact(c2)