mirror of
https://github.com/deltachat/deltachat-core.git
synced 2025-10-04 18:29:19 +02:00
make send and receive message test work, add some events
This commit is contained in:
parent
3265178d31
commit
4f5ded880e
8 changed files with 79 additions and 27 deletions
|
@ -33,7 +33,8 @@ def acfactory(pytestconfig, tmpdir, request):
|
||||||
def get_live_account(self, started=True):
|
def get_live_account(self, started=True):
|
||||||
configdict = self.configlist.pop(0)
|
configdict = self.configlist.pop(0)
|
||||||
tmpdb = tmpdir.join("testdb%d" % self.count)
|
tmpdb = tmpdir.join("testdb%d" % self.count)
|
||||||
ac = Account(tmpdb.strpath)
|
ac = Account(tmpdb.strpath, _logid="ac{}".format(self.count+1))
|
||||||
|
self.count += 1
|
||||||
ac._evlogger.set_timeout(10)
|
ac._evlogger.set_timeout(10)
|
||||||
ac.set_config(**configdict)
|
ac.set_config(**configdict)
|
||||||
if started:
|
if started:
|
||||||
|
|
|
@ -16,12 +16,18 @@ def py_dc_callback(ctx, evt, data1, data2):
|
||||||
callback = _DC_CALLBACK_MAP.get(ctx, lambda *a: 0)
|
callback = _DC_CALLBACK_MAP.get(ctx, lambda *a: 0)
|
||||||
# the following code relates to the deltachat/_build.py's helper
|
# the following code relates to the deltachat/_build.py's helper
|
||||||
# function which provides us signature info of an event call
|
# function which provides us signature info of an event call
|
||||||
|
evt_name = get_dc_event_name(evt)
|
||||||
event_sig_types = capi.lib.dc_get_event_signature_types(evt)
|
event_sig_types = capi.lib.dc_get_event_signature_types(evt)
|
||||||
if data1 and event_sig_types & 1:
|
if data1 and event_sig_types & 1:
|
||||||
data1 = ffi.string(ffi.cast('char*', data1)).decode("utf8")
|
data1 = ffi.string(ffi.cast('char*', data1)).decode("utf8")
|
||||||
if data2 and event_sig_types & 2:
|
if data2 and event_sig_types & 2:
|
||||||
data2 = ffi.string(ffi.cast('char*', data2)).decode("utf8")
|
try:
|
||||||
evt_name = get_dc_event_name(evt)
|
data2 = ffi.string(ffi.cast('char*', data2)).decode("utf8")
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
# XXX ignoring this error is not quite correct but for now
|
||||||
|
# i don't want to hunt down encoding problems in the c lib
|
||||||
|
data2 = ffi.string(ffi.cast('char*', data2))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ret = callback(ctx, evt_name, data1, data2)
|
ret = callback(ctx, evt_name, data1, data2)
|
||||||
if event_sig_types & 4:
|
if event_sig_types & 4:
|
||||||
|
|
|
@ -12,7 +12,7 @@ deltah = joinpath(dirname(dirname(dirname(here))), "src", "deltachat.h")
|
||||||
|
|
||||||
|
|
||||||
def read_event_defines():
|
def read_event_defines():
|
||||||
rex = re.compile(r'#define\s+(?:DC_EVENT_|DC_CONTACT_ID_)\S+\s+(\d+).*')
|
rex = re.compile(r'#define\s+(?:DC_EVENT_|DC_CONTACT_ID_|DC_CHAT)\S+\s+(\d+).*')
|
||||||
return filter(rex.match, open(deltah))
|
return filter(rex.match, open(deltah))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,11 +37,13 @@ class EventHandler:
|
||||||
|
|
||||||
|
|
||||||
class EventLogger:
|
class EventLogger:
|
||||||
def __init__(self, dc_context, debug=True):
|
def __init__(self, dc_context, _logid=None, debug=True):
|
||||||
self.dc_context = dc_context
|
self.dc_context = dc_context
|
||||||
self._event_queue = Queue()
|
self._event_queue = Queue()
|
||||||
self._debug = debug
|
self._debug = debug
|
||||||
self._ctxinfo = str(self.dc_context).strip(">").split()[-1]
|
if _logid is None:
|
||||||
|
_logid = str(self.dc_context).strip(">").split()[-1]
|
||||||
|
self._logid = _logid
|
||||||
self._timeout = None
|
self._timeout = None
|
||||||
|
|
||||||
def __call__(self, evt_name, data1, data2):
|
def __call__(self, evt_name, data1, data2):
|
||||||
|
@ -54,8 +56,8 @@ class EventLogger:
|
||||||
def get(self, timeout=None, check_error=True):
|
def get(self, timeout=None, check_error=True):
|
||||||
timeout = timeout or self._timeout
|
timeout = timeout or self._timeout
|
||||||
ev = self._event_queue.get(timeout=timeout)
|
ev = self._event_queue.get(timeout=timeout)
|
||||||
if check_error:
|
if check_error and ev[0] == "DC_EVENT_ERROR":
|
||||||
assert ev[0] != "DC_EVENT_ERROR"
|
raise ValueError("{}({!r},{!r})".format(*ev))
|
||||||
return ev
|
return ev
|
||||||
|
|
||||||
def get_matching(self, event_name_regex):
|
def get_matching(self, event_name_regex):
|
||||||
|
@ -70,7 +72,7 @@ class EventLogger:
|
||||||
t = threading.currentThread()
|
t = threading.currentThread()
|
||||||
tname = getattr(t, "name", t)
|
tname = getattr(t, "name", t)
|
||||||
print("[{}-{}] {}({!r},{!r})".format(
|
print("[{}-{}] {}({!r},{!r})".format(
|
||||||
tname, self._ctxinfo, evt_name, data1, data2))
|
tname, self._logid, evt_name, data1, data2))
|
||||||
|
|
||||||
|
|
||||||
class Contact:
|
class Contact:
|
||||||
|
@ -103,12 +105,15 @@ class Chat:
|
||||||
self.id = chat_id
|
self.id = chat_id
|
||||||
|
|
||||||
def send_text_message(self, msg):
|
def send_text_message(self, msg):
|
||||||
|
""" return ID of the message in this chat.
|
||||||
|
'msg' should be unicode"""
|
||||||
msg = convert_bytes(msg)
|
msg = convert_bytes(msg)
|
||||||
|
print ("chat id", self.id)
|
||||||
return capi.lib.dc_send_text_msg(self.dc_context, self.id, msg)
|
return capi.lib.dc_send_text_msg(self.dc_context, self.id, msg)
|
||||||
|
|
||||||
|
|
||||||
class Account:
|
class Account:
|
||||||
def __init__(self, db_path):
|
def __init__(self, db_path, _logid=None):
|
||||||
self.dc_context = ctx = capi.lib.dc_context_new(
|
self.dc_context = ctx = capi.lib.dc_context_new(
|
||||||
capi.lib.py_dc_callback,
|
capi.lib.py_dc_callback,
|
||||||
capi.ffi.NULL, capi.ffi.NULL)
|
capi.ffi.NULL, capi.ffi.NULL)
|
||||||
|
@ -116,7 +121,7 @@ class Account:
|
||||||
db_path = db_path.encode("utf8")
|
db_path = db_path.encode("utf8")
|
||||||
capi.lib.dc_open(ctx, db_path, capi.ffi.NULL)
|
capi.lib.dc_open(ctx, db_path, capi.ffi.NULL)
|
||||||
self._evhandler = EventHandler(self.dc_context)
|
self._evhandler = EventHandler(self.dc_context)
|
||||||
self._evlogger = EventLogger(self.dc_context)
|
self._evlogger = EventLogger(self.dc_context, _logid)
|
||||||
self._threads = IOThreads(self.dc_context)
|
self._threads = IOThreads(self.dc_context)
|
||||||
|
|
||||||
def set_config(self, **kwargs):
|
def set_config(self, **kwargs):
|
||||||
|
@ -133,14 +138,15 @@ class Account:
|
||||||
def get_self_contact(self):
|
def get_self_contact(self):
|
||||||
return Contact(self.dc_context, capi.lib.DC_CONTACT_ID_SELF)
|
return Contact(self.dc_context, capi.lib.DC_CONTACT_ID_SELF)
|
||||||
|
|
||||||
def create_contact(self, emailadr, name=ffi.NULL):
|
def create_contact(self, email, name=ffi.NULL):
|
||||||
name = convert_bytes(name)
|
name = convert_bytes(name)
|
||||||
emailadr = convert_bytes(emailadr)
|
email = convert_bytes(email)
|
||||||
contact_id = capi.lib.dc_create_contact(self.dc_context, name, emailadr)
|
contact_id = capi.lib.dc_create_contact(self.dc_context, name, email)
|
||||||
return Contact(self.dc_context, contact_id)
|
return Contact(self.dc_context, contact_id)
|
||||||
|
|
||||||
def create_chat_by_contact(self, contact):
|
def create_chat_by_contact(self, contact):
|
||||||
chat_id = capi.lib.dc_create_chat_by_contact_id(self.dc_context, contact.id)
|
chat_id = capi.lib.dc_create_chat_by_contact_id(self.dc_context, contact.id)
|
||||||
|
assert chat_id >= capi.lib.DC_CHAT_ID_LAST_SPECIAL, chat_id
|
||||||
return Chat(self.dc_context, chat_id)
|
return Chat(self.dc_context, chat_id)
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import re
|
import time
|
||||||
|
from deltachat.capi import lib
|
||||||
|
|
||||||
|
|
||||||
class TestLive:
|
class TestLive:
|
||||||
|
@ -12,7 +13,7 @@ class TestLive:
|
||||||
|
|
||||||
def test_contacts(self, acfactory):
|
def test_contacts(self, acfactory):
|
||||||
ac1 = acfactory.get_live_account(started=False)
|
ac1 = acfactory.get_live_account(started=False)
|
||||||
contact1 = ac1.create_contact("some1@hello.com", name="some1")
|
contact1 = ac1.create_contact(email="some1@hello.com", name="some1")
|
||||||
assert contact1.id
|
assert contact1.id
|
||||||
assert contact1.addr == "some1@hello.com"
|
assert contact1.addr == "some1@hello.com"
|
||||||
assert contact1.display_name == "some1"
|
assert contact1.display_name == "some1"
|
||||||
|
@ -25,25 +26,50 @@ class TestLive:
|
||||||
chat = ac1.create_chat_by_contact(contact1)
|
chat = ac1.create_chat_by_contact(contact1)
|
||||||
assert chat.id
|
assert chat.id
|
||||||
|
|
||||||
def test_basic_configure_login_ok(self, acfactory):
|
def wait_successful_IMAP_SMTP_connection(self, account):
|
||||||
ac1 = acfactory.get_live_account()
|
|
||||||
imap_ok = smtp_ok = False
|
imap_ok = smtp_ok = False
|
||||||
while not imap_ok or not smtp_ok:
|
while not imap_ok or not smtp_ok:
|
||||||
evt_name, data1, data2 = \
|
evt_name, data1, data2 = \
|
||||||
ac1._evlogger.get_matching("DC_EVENT_(IMAP|SMTP)_CONNECTED")
|
account._evlogger.get_matching("DC_EVENT_(IMAP|SMTP)_CONNECTED")
|
||||||
if evt_name == "DC_EVENT_IMAP_CONNECTED":
|
if evt_name == "DC_EVENT_IMAP_CONNECTED":
|
||||||
imap_ok = True
|
imap_ok = True
|
||||||
if evt_name == "DC_EVENT_SMTP_CONNECTED":
|
if evt_name == "DC_EVENT_SMTP_CONNECTED":
|
||||||
smtp_ok = True
|
smtp_ok = True
|
||||||
|
print("** IMAP and SMTP logins successful", account.dc_context)
|
||||||
|
|
||||||
|
def wait_configuration_progress(self, account, target):
|
||||||
|
while 1:
|
||||||
|
evt_name, data1, data2 = \
|
||||||
|
account._evlogger.get_matching("DC_EVENT_CONFIGURE_PROGRESS")
|
||||||
|
if data1 >= target:
|
||||||
|
print("** CONFIG PROGRESS {}".format(target), account.dc_context)
|
||||||
|
break
|
||||||
|
|
||||||
|
def test_basic_configure_login_ok(self, acfactory):
|
||||||
|
ac1 = acfactory.get_live_account()
|
||||||
|
self.wait_successful_IMAP_SMTP_connection(ac1)
|
||||||
|
self.wait_configuration_progress(ac1, 1000)
|
||||||
assert ac1.get_config("mail_pw")
|
assert ac1.get_config("mail_pw")
|
||||||
|
|
||||||
def test_send_message(self, acfactory):
|
def test_send_message(self, acfactory):
|
||||||
return
|
ac1 = acfactory.get_live_account()
|
||||||
ac1, ev1 = acfactory.get_live_account()
|
ac2 = acfactory.get_live_account()
|
||||||
ac2, ev2 = acfactory.get_live_account()
|
c2 = ac1.create_contact(email=ac2.get_config("addr"))
|
||||||
c2 = ac2.get_self_contact()
|
|
||||||
chat = ac1.create_chat_by_contact(c2)
|
chat = ac1.create_chat_by_contact(c2)
|
||||||
import time
|
assert chat.id >= lib.DC_CHAT_ID_LAST_SPECIAL
|
||||||
time.sleep(5)
|
|
||||||
print ("sending test message")
|
self.wait_successful_IMAP_SMTP_connection(ac1)
|
||||||
chat.send_text_message("msg1")
|
self.wait_successful_IMAP_SMTP_connection(ac2)
|
||||||
|
self.wait_configuration_progress(ac1, 1000)
|
||||||
|
self.wait_configuration_progress(ac2, 1000)
|
||||||
|
msgnum = chat.send_text_message("msg1")
|
||||||
|
ev = ac1._evlogger.get_matching("DC_EVENT_MSG_DELIVERED")
|
||||||
|
evt_name, data1, data2 = ev
|
||||||
|
assert data1 == chat.id
|
||||||
|
assert data2 == msgnum
|
||||||
|
starttime = time.time()
|
||||||
|
while time.time() < starttime + 20:
|
||||||
|
evt_name, data1, data2 = ac2._evlogger.get_matching("DC_EVENT_INFO")
|
||||||
|
if "1 mails read" in data2:
|
||||||
|
break
|
||||||
|
print("ignoring event", evt_name, data1, data2)
|
||||||
|
|
|
@ -2181,6 +2181,7 @@ uint32_t dc_send_text_msg(dc_context_t* context, uint32_t chat_id, const char* t
|
||||||
uint32_t ret = 0;
|
uint32_t ret = 0;
|
||||||
|
|
||||||
if (context==NULL || context->magic!=DC_CONTEXT_MAGIC || chat_id<=DC_CHAT_ID_LAST_SPECIAL || text_to_send==NULL) {
|
if (context==NULL || context->magic!=DC_CONTEXT_MAGIC || chat_id<=DC_CHAT_ID_LAST_SPECIAL || text_to_send==NULL) {
|
||||||
|
dc_log_info(context, 0, "some error");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -311,6 +311,8 @@ int dc_smtp_send_msg(dc_smtp_t* smtp, const clist* recipients, const char* data_
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dc_log_event(smtp->context, DC_EVENT_SMTP_MESSAGE_SENT, 0,
|
||||||
|
"Message was sent to SMTP server");
|
||||||
success = 1;
|
success = 1;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
|
@ -785,6 +785,16 @@ time_t dc_lot_get_timestamp (const dc_lot_t*);
|
||||||
*/
|
*/
|
||||||
#define DC_EVENT_IMAP_CONNECTED 102
|
#define DC_EVENT_IMAP_CONNECTED 102
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when a message was successfully sent to the SMTP server.
|
||||||
|
*
|
||||||
|
* @param data1 0
|
||||||
|
* @param data2 (const char*) Info string in english language.
|
||||||
|
* Must not be free()'d or modified and is valid only until the callback returns.
|
||||||
|
* @return 0
|
||||||
|
*/
|
||||||
|
#define DC_EVENT_SMTP_MESSAGE_SENT 103
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The library-user should write a warning string to the log.
|
* The library-user should write a warning string to the log.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue