mirror of
https://github.com/chatmail/core.git
synced 2026-05-09 01:46:30 +03:00
- perform direct_imap init in testplugin instead of global deltachat
plugin, probably also helping to avoid some segfeaults during teardown - some API renaming on the side (too hard to split into separate commit, sorry)
This commit is contained in:
@@ -8,7 +8,6 @@ import ssl
|
|||||||
import pathlib
|
import pathlib
|
||||||
from imap_tools import MailBox, MailBoxTls, errors, AND, Header, MailMessageFlags, MailMessage
|
from imap_tools import MailBox, MailBoxTls, errors, AND, Header, MailMessageFlags, MailMessage
|
||||||
import imaplib
|
import imaplib
|
||||||
import deltachat
|
|
||||||
from deltachat import const, Account
|
from deltachat import const, Account
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
@@ -18,44 +17,6 @@ FETCH = b'FETCH'
|
|||||||
ALL = "1:*"
|
ALL = "1:*"
|
||||||
|
|
||||||
|
|
||||||
@deltachat.global_hookimpl
|
|
||||||
def dc_account_extra_configure(account: Account):
|
|
||||||
""" Reset the account (we reuse accounts across tests)
|
|
||||||
and make 'account.direct_imap' available for direct IMAP ops.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
|
|
||||||
if not hasattr(account, "direct_imap"):
|
|
||||||
imap = DirectImap(account)
|
|
||||||
|
|
||||||
for folder in imap.list_folders():
|
|
||||||
if folder.lower() == "inbox" or folder.lower() == "deltachat":
|
|
||||||
assert imap.select_folder(folder)
|
|
||||||
imap.delete(ALL, expunge=True)
|
|
||||||
else:
|
|
||||||
imap.conn.folder.delete(folder)
|
|
||||||
# We just deleted the folder, so we have to make DC forget about it, too
|
|
||||||
if account.get_config("configured_sentbox_folder") == folder:
|
|
||||||
account.set_config("configured_sentbox_folder", None)
|
|
||||||
|
|
||||||
setattr(account, "direct_imap", imap)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
# Uncaught exceptions here would lead to a timeout without any note written to the log
|
|
||||||
# start with DC_EVENT_WARNING so that the line is printed in yellow and won't be overlooked when reading
|
|
||||||
account.log("DC_EVENT_WARNING =================== DIRECT_IMAP CAN'T RESET ACCOUNT: ===================")
|
|
||||||
account.log("DC_EVENT_WARNING =================== " + str(e) + " ===================")
|
|
||||||
|
|
||||||
|
|
||||||
@deltachat.global_hookimpl
|
|
||||||
def dc_account_after_shutdown(account):
|
|
||||||
""" shutdown the imap connection if there is one. """
|
|
||||||
imap = getattr(account, "direct_imap", None)
|
|
||||||
if imap is not None:
|
|
||||||
imap.shutdown()
|
|
||||||
del account.direct_imap
|
|
||||||
|
|
||||||
|
|
||||||
class DirectImap:
|
class DirectImap:
|
||||||
def __init__(self, account: Account) -> None:
|
def __init__(self, account: Account) -> None:
|
||||||
self.account = account
|
self.account = account
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import requests
|
|||||||
from . import Account, const
|
from . import Account, const
|
||||||
from .events import FFIEventLogger, FFIEventTracker
|
from .events import FFIEventLogger, FFIEventTracker
|
||||||
from _pytest._code import Source
|
from _pytest._code import Source
|
||||||
from deltachat import direct_imap
|
from deltachat.direct_imap import DirectImap
|
||||||
|
|
||||||
import deltachat
|
import deltachat
|
||||||
|
|
||||||
@@ -215,7 +215,6 @@ class ACFactory:
|
|||||||
self._preconfigured_keys = ["alice", "bob", "charlie",
|
self._preconfigured_keys = ["alice", "bob", "charlie",
|
||||||
"dom", "elena", "fiona"]
|
"dom", "elena", "fiona"]
|
||||||
self.set_logging_default(False)
|
self.set_logging_default(False)
|
||||||
deltachat.register_global_plugin(direct_imap)
|
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
while self._finalizers:
|
while self._finalizers:
|
||||||
@@ -224,9 +223,12 @@ class ACFactory:
|
|||||||
|
|
||||||
while self._accounts:
|
while self._accounts:
|
||||||
acc = self._accounts.pop()
|
acc = self._accounts.pop()
|
||||||
|
imap = getattr(acc, "direct_imap", None)
|
||||||
|
if imap is not None:
|
||||||
|
imap.shutdown()
|
||||||
|
del acc.direct_imap
|
||||||
acc.shutdown()
|
acc.shutdown()
|
||||||
acc.disable_logging()
|
acc.disable_logging()
|
||||||
deltachat.unregister_global_plugin(direct_imap)
|
|
||||||
|
|
||||||
def get_next_liveconfig(self):
|
def get_next_liveconfig(self):
|
||||||
""" Base function to get functional online configurations
|
""" Base function to get functional online configurations
|
||||||
@@ -303,13 +305,7 @@ class ACFactory:
|
|||||||
self._preconfigure_key(ac, configdict["addr"])
|
self._preconfigure_key(ac, configdict["addr"])
|
||||||
ac.update_config(configdict)
|
ac.update_config(configdict)
|
||||||
|
|
||||||
def get_online_accounts(self, num):
|
def get_cloned_configuring_account(self, account):
|
||||||
# to reduce number of log events logging starts after accounts can receive
|
|
||||||
accounts = [self.get_online_configuring_account() for i in range(num)]
|
|
||||||
self.wait_configure_and_start_io(logstart="after_inbox_idle_ready")
|
|
||||||
return accounts
|
|
||||||
|
|
||||||
def clone_online_account(self, account):
|
|
||||||
""" Clones addr, mail_pw, mvbox_move, sentbox_watch and the
|
""" Clones addr, mail_pw, mvbox_move, sentbox_watch and the
|
||||||
direct_imap object of an online account. This simulates the user setting
|
direct_imap object of an online account. This simulates the user setting
|
||||||
up a new device without importing a backup.
|
up a new device without importing a backup.
|
||||||
@@ -348,14 +344,21 @@ class ACFactory:
|
|||||||
acc._evtracker.consume_events()
|
acc._evtracker.consume_events()
|
||||||
acc.get_device_chat().mark_noticed()
|
acc.get_device_chat().mark_noticed()
|
||||||
del acc._configtracker
|
del acc._configtracker
|
||||||
|
if not hasattr(acc, "direct_imap"):
|
||||||
|
self.init_direct_imap(acc)
|
||||||
|
|
||||||
|
def get_online_accounts(self, num):
|
||||||
|
# to reduce number of log events logging starts after accounts can receive
|
||||||
|
accounts = [self.get_online_configuring_account() for i in range(num)]
|
||||||
|
self.wait_configure_and_start_io(logstart="after_inbox_idle_ready")
|
||||||
|
return accounts
|
||||||
|
|
||||||
def run_bot_process(self, module, ffi=True):
|
def run_bot_process(self, module, ffi=True):
|
||||||
fn = module.__file__
|
fn = module.__file__
|
||||||
|
|
||||||
bot_cfg = self.get_next_liveconfig()
|
bot_cfg = self.get_next_liveconfig()
|
||||||
bot_ac = self.get_unconfigured_account()
|
bot_ac = self.get_unconfigured_account()
|
||||||
bot_ac.update_config(bot_cfg)
|
self.prepare_account_with_liveconfig(bot_ac, bot_cfg)
|
||||||
self._preconfigure_key(bot_ac, bot_cfg["addr"])
|
|
||||||
|
|
||||||
# Avoid starting ac so we don't interfere with the bot operating on
|
# Avoid starting ac so we don't interfere with the bot operating on
|
||||||
# the same database.
|
# the same database.
|
||||||
@@ -385,6 +388,16 @@ class ACFactory:
|
|||||||
self._finalizers.append(bot.kill)
|
self._finalizers.append(bot.kill)
|
||||||
return bot
|
return bot
|
||||||
|
|
||||||
|
def init_direct_imap(self, acc):
|
||||||
|
if not hasattr(acc, "direct_imap"):
|
||||||
|
acc.direct_imap = imap = DirectImap(acc)
|
||||||
|
for folder in imap.list_folders():
|
||||||
|
if folder.lower() == "inbox" or folder.lower() == "deltachat":
|
||||||
|
assert imap.select_folder(folder)
|
||||||
|
imap.delete("1:*", expunge=True)
|
||||||
|
else:
|
||||||
|
imap.conn.folder.delete(folder)
|
||||||
|
|
||||||
def dump_imap_summary(self, logfile):
|
def dump_imap_summary(self, logfile):
|
||||||
for ac in self._accounts:
|
for ac in self._accounts:
|
||||||
ac.dump_account_info(logfile=logfile)
|
ac.dump_account_info(logfile=logfile)
|
||||||
|
|||||||
@@ -727,15 +727,12 @@ class TestOnlineAccount:
|
|||||||
def test_one_account_send_bcc_setting(self, acfactory, lp):
|
def test_one_account_send_bcc_setting(self, acfactory, lp):
|
||||||
ac1 = acfactory.get_online_configuring_account()
|
ac1 = acfactory.get_online_configuring_account()
|
||||||
ac2 = acfactory.get_online_configuring_account()
|
ac2 = acfactory.get_online_configuring_account()
|
||||||
|
ac1_clone = acfactory.get_cloned_configuring_account(ac1)
|
||||||
# Clone the first account: we will test if sent messages
|
|
||||||
# are copied to it via BCC.
|
|
||||||
ac1_clone = acfactory.clone_online_account(ac1)
|
|
||||||
|
|
||||||
acfactory.wait_configure_and_start_io()
|
acfactory.wait_configure_and_start_io()
|
||||||
|
|
||||||
chat = acfactory.get_accepted_chat(ac1, ac2)
|
# test if sent messages are copied to it via BCC.
|
||||||
|
|
||||||
|
chat = acfactory.get_accepted_chat(ac1, ac2)
|
||||||
self_addr = ac1.get_config("addr")
|
self_addr = ac1.get_config("addr")
|
||||||
other_addr = ac2.get_config("addr")
|
other_addr = ac2.get_config("addr")
|
||||||
|
|
||||||
@@ -1094,7 +1091,7 @@ class TestOnlineAccount:
|
|||||||
"""Test that message marked as seen on one device is marked as seen on another."""
|
"""Test that message marked as seen on one device is marked as seen on another."""
|
||||||
ac1 = acfactory.get_online_configuring_account()
|
ac1 = acfactory.get_online_configuring_account()
|
||||||
ac2 = acfactory.get_online_configuring_account()
|
ac2 = acfactory.get_online_configuring_account()
|
||||||
ac1_clone = acfactory.clone_online_account(ac1)
|
ac1_clone = acfactory.get_cloned_configuring_account(ac1)
|
||||||
acfactory.wait_configure_and_start_io()
|
acfactory.wait_configure_and_start_io()
|
||||||
|
|
||||||
ac1.set_config("bcc_self", "1")
|
ac1.set_config("bcc_self", "1")
|
||||||
@@ -1535,7 +1532,7 @@ class TestOnlineAccount:
|
|||||||
def test_no_old_msg_is_fresh(self, acfactory, lp):
|
def test_no_old_msg_is_fresh(self, acfactory, lp):
|
||||||
ac1 = acfactory.get_online_configuring_account()
|
ac1 = acfactory.get_online_configuring_account()
|
||||||
ac2 = acfactory.get_online_configuring_account()
|
ac2 = acfactory.get_online_configuring_account()
|
||||||
ac1_clone = acfactory.clone_online_account(ac1)
|
ac1_clone = acfactory.get_cloned_configuring_account(ac1)
|
||||||
acfactory.wait_configure_and_start_io()
|
acfactory.wait_configure_and_start_io()
|
||||||
|
|
||||||
ac1.set_config("e2ee_enabled", "0")
|
ac1.set_config("e2ee_enabled", "0")
|
||||||
@@ -1899,7 +1896,7 @@ class TestOnlineAccount:
|
|||||||
# before ther setup message is send. DC does not read old messages
|
# before ther setup message is send. DC does not read old messages
|
||||||
# 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.get_cloned_configuring_account(ac1)
|
||||||
acfactory.wait_configure_and_start_io()
|
acfactory.wait_configure_and_start_io()
|
||||||
|
|
||||||
lp.sec("trigger ac setup message and return setupcode")
|
lp.sec("trigger ac setup message and return setupcode")
|
||||||
@@ -1920,7 +1917,7 @@ class TestOnlineAccount:
|
|||||||
|
|
||||||
def test_ac_setup_message_twice(self, acfactory, lp):
|
def test_ac_setup_message_twice(self, acfactory, lp):
|
||||||
ac1 = acfactory.get_online_configuring_account()
|
ac1 = acfactory.get_online_configuring_account()
|
||||||
ac2 = acfactory.clone_online_account(ac1)
|
ac2 = acfactory.get_cloned_configuring_account(ac1)
|
||||||
acfactory.wait_configure_and_start_io()
|
acfactory.wait_configure_and_start_io()
|
||||||
|
|
||||||
lp.sec("trigger ac setup message but ignore")
|
lp.sec("trigger ac setup message but ignore")
|
||||||
@@ -2404,7 +2401,7 @@ class TestOnlineAccount:
|
|||||||
lp.sec("ac3 reinstalls DC and generates a new key")
|
lp.sec("ac3 reinstalls DC and generates a new key")
|
||||||
ac3.stop_io()
|
ac3.stop_io()
|
||||||
acfactory.remove_preconfigured_keys()
|
acfactory.remove_preconfigured_keys()
|
||||||
ac4 = acfactory.clone_online_account(ac3)
|
ac4 = acfactory.get_cloned_configuring_account(ac3)
|
||||||
ac4._configtracker.wait_finish()
|
ac4._configtracker.wait_finish()
|
||||||
# Create contacts to make sure incoming messages are not treated as contact requests
|
# Create contacts to make sure incoming messages are not treated as contact requests
|
||||||
chat41 = ac4.create_chat(ac1)
|
chat41 = ac4.create_chat(ac1)
|
||||||
@@ -2810,7 +2807,7 @@ class TestOnlineAccount:
|
|||||||
assert_folders_configured(ac1)
|
assert_folders_configured(ac1)
|
||||||
|
|
||||||
lp.sec("create a cloned ac1 and fetch contact history during configure")
|
lp.sec("create a cloned ac1 and fetch contact history during configure")
|
||||||
ac1_clone = acfactory.clone_online_account(ac1)
|
ac1_clone = acfactory.get_cloned_configuring_account(ac1)
|
||||||
ac1_clone.set_config("fetch_existing_msgs", "1")
|
ac1_clone.set_config("fetch_existing_msgs", "1")
|
||||||
ac1_clone._configtracker.wait_finish()
|
ac1_clone._configtracker.wait_finish()
|
||||||
ac1_clone.start_io()
|
ac1_clone.start_io()
|
||||||
@@ -2855,7 +2852,7 @@ class TestOnlineAccount:
|
|||||||
assert ac1.direct_imap.idle_wait_for_seen()
|
assert ac1.direct_imap.idle_wait_for_seen()
|
||||||
|
|
||||||
lp.sec("Clone online account and let it fetch the existing messages")
|
lp.sec("Clone online account and let it fetch the existing messages")
|
||||||
ac1_clone = acfactory.clone_online_account(ac1)
|
ac1_clone = acfactory.get_cloned_configuring_account(ac1)
|
||||||
ac1_clone.set_config("fetch_existing_msgs", "1")
|
ac1_clone.set_config("fetch_existing_msgs", "1")
|
||||||
ac1_clone._configtracker.wait_finish()
|
ac1_clone._configtracker.wait_finish()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user