Compare commits

...

9 Commits

Author SHA1 Message Date
link2xt
19f41bd348 enable rerun only for a single test 2023-02-16 12:43:53 +00:00
link2xt
13b3933d5c work around flaky mailadm 2023-02-16 12:43:53 +00:00
link2xt
a91df13782 Insert sleep 2023-02-16 12:43:53 +00:00
link2xt
0bcaab7ebf Add info messages to add_all_recipients_as_contacts 2023-02-16 12:43:53 +00:00
link2xt
1f56bb9126 Revert "Emit ContactsChanged events from add_or_lookup_contact_by_addr()"
This reverts commit edd893507cb8d4dd6fc9c11a0c1a4bd6b2a994d4.
2023-02-16 12:43:53 +00:00
link2xt
4bc23c3fb9 Set fetch_existing_msgs without race condition 2023-02-16 12:43:53 +00:00
link2xt
a05cb61989 Emit ContactsChanged events from add_or_lookup_contact_by_addr() 2023-02-16 12:43:53 +00:00
link2xt
a20bc21c19 imap: add info events when fetching existing messages 2023-02-16 12:43:52 +00:00
link2xt
88a047b003 imap: resultify add_all_recipients_as_contacts() 2023-02-16 12:43:23 +00:00
4 changed files with 81 additions and 50 deletions

View File

@@ -150,6 +150,18 @@ class TestProcess:
self._addr2files = {}
self._configlist = []
def request_liveconfig_via_url(self, url):
for retry in range(5):
res = requests.post(url)
if res.status_code == 200:
d = res.json()
config = dict(addr=d["email"], mail_pw=d["password"])
return config
else:
print("Error requesting new temporary account (code={}): {}".format(res.status_code, res.text))
time.sleep(5)
return None
def get_liveconfig_producer(self):
"""provide live account configs, cached on a per-test-process scope
so that test functions can re-use already known live configs.
@@ -176,11 +188,9 @@ class TestProcess:
try:
yield self._configlist[index]
except IndexError:
res = requests.post(liveconfig_opt)
if res.status_code != 200:
pytest.fail("newtmpuser count={} code={}: '{}'".format(index, res.status_code, res.text))
d = res.json()
config = dict(addr=d["email"], mail_pw=d["password"])
config = self.request_liveconfig_via_url(liveconfig_opt)
if config is None:
pytest.fail("Failed to request temporary account count={}".format(index))
print("newtmpuser {}: addr={}".format(index, config["addr"]))
self._configlist.append(config)
yield config

View File

@@ -1,9 +1,11 @@
import sys
import time
import pytest
class TestGroupStressTests:
@pytest.mark.flaky(reruns=2)
def test_group_many_members_add_leave_remove(self, acfactory, lp):
accounts = acfactory.get_online_accounts(5)
acfactory.introduce_each_other(accounts)
@@ -220,22 +222,35 @@ def test_fetch_existing(acfactory, lp, mvbox_move):
assert idle1.wait_for_seen()
assert_folders_configured(ac1)
time.sleep(30) # Wait until the message is indexed.
lp.sec("create a cloned ac1 and fetch contact history during configure")
ac1_clone = acfactory.new_online_configuring_account(cloned_from=ac1)
ac1_clone.set_config("fetch_existing_msgs", "1")
ac1_clone = acfactory.new_online_configuring_account(cloned_from=ac1, fetch_existing_msgs=True)
acfactory.wait_configured(ac1_clone)
ac1_clone.start_io()
assert_folders_configured(ac1_clone)
lp.sec("check that ac2 contact was fetchted during configure")
for ev in ac1_clone._evtracker.iter_events():
if ev.name == "DC_EVENT_INFO" and "Started fetching existing contacts." in ev.data2:
break
ac1_clone._evtracker.get_matching("DC_EVENT_CONTACTS_CHANGED")
ac2_addr = ac2.get_config("addr")
assert any(c.addr == ac2_addr for c in ac1_clone.get_contacts())
for ev in ac1_clone._evtracker.iter_events():
if ev.name == "DC_EVENT_INFO" and "Done fetching existing contacts." in ev.data2:
break
assert_folders_configured(ac1_clone)
lp.sec("check that messages changed events arrive for the correct message")
for ev in ac1_clone._evtracker.iter_events():
if ev.name == "DC_EVENT_INFO" and "Started fetching existing messages." in ev.data2:
break
msg = ac1_clone._evtracker.wait_next_messages_changed()
assert msg.text == "message text"
for ev in ac1_clone._evtracker.iter_events():
if ev.name == "DC_EVENT_INFO" and "Done fetching existing messages." in ev.data2:
break
assert_folders_configured(ac1)
assert_folders_configured(ac1_clone)

View File

@@ -8,7 +8,7 @@ envlist =
[testenv]
commands =
pytest -n6 --extra-info --reruns 2 --reruns-delay 5 -v -rsXx --ignored --strict-tls {posargs: tests examples}
pytest -n6 --extra-info -v -rsXx --ignored --strict-tls {posargs: tests examples}
pip wheel . -w {toxworkdir}/wheelhouse --no-deps
passenv =
DCC_RS_DEV

View File

@@ -919,11 +919,14 @@ impl Imap {
}
self.prepare(context).await.context("could not connect")?;
add_all_recipients_as_contacts(context, self, Config::ConfiguredSentboxFolder).await;
add_all_recipients_as_contacts(context, self, Config::ConfiguredMvboxFolder).await;
add_all_recipients_as_contacts(context, self, Config::ConfiguredInboxFolder).await;
info!(context, "Started fetching existing contacts.");
add_all_recipients_as_contacts(context, self, Config::ConfiguredSentboxFolder).await?;
add_all_recipients_as_contacts(context, self, Config::ConfiguredMvboxFolder).await?;
add_all_recipients_as_contacts(context, self, Config::ConfiguredInboxFolder).await?;
info!(context, "Done fetching existing contacts.");
if context.get_config_bool(Config::FetchExistingMsgs).await? {
info!(context, "Started fetching existing messages.");
for config in &[
Config::ConfiguredMvboxFolder,
Config::ConfiguredInboxFolder,
@@ -935,9 +938,11 @@ impl Imap {
.context("could not fetch messages")?;
}
}
info!(context, "Done fetching existing messages.");
} else {
info!(context, "Not fetching existing messages.");
}
info!(context, "Done fetching existing messages.");
context
.set_config_bool(Config::FetchedExistingMsgs, true)
.await?;
@@ -2334,49 +2339,50 @@ impl std::fmt::Display for UidRange {
}
}
}
async fn add_all_recipients_as_contacts(context: &Context, imap: &mut Imap, folder: Config) {
let mailbox = if let Ok(Some(m)) = context.get_config(folder).await {
async fn add_all_recipients_as_contacts(
context: &Context,
imap: &mut Imap,
folder: Config,
) -> Result<()> {
let mailbox = if let Some(m) = context.get_config(folder).await? {
m
} else {
return;
return Ok(());
};
if let Err(e) = imap.select_with_uidvalidity(context, &mailbox).await {
// We are using Anyhow's .context() and to show the inner error, too, we need the {:#}:
warn!(context, "Could not select {}: {:#}", mailbox, e);
return;
}
match imap.get_all_recipients(context).await {
Ok(contacts) => {
let mut any_modified = false;
for contact in contacts {
let display_name_normalized = contact
.display_name
.as_ref()
.map(|s| normalize_name(s))
.unwrap_or_default();
imap.select_with_uidvalidity(context, &mailbox).await?;
let contacts = imap
.get_all_recipients(context)
.await
.context("could not get recipients")?;
match Contact::add_or_lookup(
context,
&display_name_normalized,
&contact.addr,
Origin::OutgoingTo,
)
.await
{
Ok((_, modified)) => {
if modified != Modifier::None {
any_modified = true;
}
}
Err(e) => warn!(context, "Could not add recipient: {}", e),
}
}
if any_modified {
context.emit_event(EventType::ContactsChanged(None));
}
let mut any_modified = false;
for contact in contacts {
let display_name_normalized = contact
.display_name
.as_ref()
.map(|s| normalize_name(s))
.unwrap_or_default();
let (_, modified) = Contact::add_or_lookup(
context,
&display_name_normalized,
&contact.addr,
Origin::OutgoingTo,
)
.await
.context("could not add recipient")?;
if modified != Modifier::None {
any_modified = true;
}
Err(e) => warn!(context, "Could not add recipients: {}", e),
};
}
if any_modified {
context.emit_event(EventType::ContactsChanged(None));
info!(context, "Collected some contacts from folder {}", mailbox);
} else {
info!(context, "Collected no contacts from folder {}", mailbox);
}
Ok(())
}
#[cfg(test)]