From 46175a3d521f562f225d5373dce12c473bc45018 Mon Sep 17 00:00:00 2001 From: Edouard Tisserant Date: Tue, 6 Sep 2016 18:47:17 +0200 Subject: [PATCH] Better multi-process test. Still PEP_MESSAGE_CONSUMED needs to be supported --- test/mp_sync_test.py | 13 ++--- test/multipEp.py | 125 ++++++++++++++++++++++++++----------------- 2 files changed, 80 insertions(+), 58 deletions(-) diff --git a/test/mp_sync_test.py b/test/mp_sync_test.py index c35fd34..6f6d88b 100644 --- a/test/mp_sync_test.py +++ b/test/mp_sync_test.py @@ -1,5 +1,5 @@ """ -test for simplest keysync scenario : two device setting up sam account +test for simplest keysync scenario : two device setting up same account Launch it with something like : DYLD_LIBRARY_PATH=/Users/ed/lib/ PYTHONPATH=`pwd`/../build/lib.macosx-10.11-x86_64-3.4 python3.4 sync_test.py @@ -8,11 +8,6 @@ DYLD_LIBRARY_PATH=/Users/ed/lib/ PYTHONPATH=`pwd`/../build/lib.macosx-10.11-x86_ import multipEp as mp -def create_account(address, name): - i = mp.pEp.Identity(address, name) - mp.pEp.myself(i) - mp.own_addresses.append(address) - # unused def send_message(from_address, to_address): m = mp.pEp.outgoing_message(Identity(from_address, from_address)) @@ -24,8 +19,10 @@ def send_message(from_address, to_address): scenario0 = [ #("instance name", ["func name", [args], {kwargs}]), - ("A", [create_account, ["some.one@some.where", "Some One"]]), - ("B", [create_account, ["some.one@some.where", "Some One"]]) + ("A", [mp.create_account, ["some.one@some.where", "Some One"]]), + ("B", [mp.create_account, ["some.one@some.where", "Some One"]]), + ("A", [None, None]), + ("B", [None, None]) ] if __name__ == "__main__": diff --git a/test/multipEp.py b/test/multipEp.py index e83f1ef..a1c8f02 100644 --- a/test/multipEp.py +++ b/test/multipEp.py @@ -8,27 +8,48 @@ from collections import OrderedDict pEp = None handler = None own_addresses = [] -sent_messages = [] -def pEp_instance_run(iname, conn): - global pEp, handler, sent_messages +def create_account(address, name): + global own_addresses + i = pEp.Identity(address, name) + pEp.myself(i) + own_addresses.append(address) + +def header(blah=None): + if blah is None: + return "-" * 80 + else: + return ("-" * (39 - int(len(blah)/2)) + + " " + blah + " " + + "-" * (39 - len(blah) + int(len(blah)/2))) - pEp = importlib.import_module("pEp") - hdr = "-" * (39 - int(len(iname)/2)) + " " + iname + " " + "-" * (39 - len(iname) + int(len(iname)/2)) +def pEp_instance_run(iname, conn, msgs_folders): + global pEp, handler, own_addresses + + pEp = importlib.import_module("pEp") class Handler(pEp.SyncMixIn): def messageToSend(self, msg): - msgstr = str(msg) - print(hdr) - print(msgstr.replace("\r", "")) - print("-" * 80) - sent_messages.append(msgstr) + print(header("SYNC MESSAGE from instance"+iname)) + print("from :", msg.from_) + print("to :", msg.to) + print("short :", msg.shortmsg) + print("long :", (msg.longmsg[:250]+" [...]" + if len(msg.longmsg)>250 + else msg.longmsg)) + print(msg.attachments) + print(header()) + for rcpt in msg.to + msg.cc + msg.bcc: + # list inside dict from MP manager are not mutable, apparently. + msgs = msgs_folders.get(rcpt.address,[]) + msgs.append(str(msg)) + msgs_folders[rcpt.address] = msgs def showHandshake(self, me, partner): - print(hdr) + print(header("HANDSHAKE from instance"+iname)) print("handshake needed between " + repr(me) + " and " + repr(partner)) - print("-" * 80) + print(header()) # TODO: accept or reject handler = Handler() @@ -38,56 +59,60 @@ def pEp_instance_run(iname, conn): if order is None: break - command, new_msgs = order + func = order[0] - if new_msgs is not None: - for msgstr in new_msgs: + print(header("DECRYPT messages for instance "+iname)) + # decrypt every non-consumed message for all instance accounts + for own_address in own_addresses: + msgs_for_me = msgs_folders[own_address] + for idx, msgstr in enumerate(msgs_for_me): msg = pEp.incoming_message(msgstr) - for to in msg.to: - # check if mail is for an account owned by that instance - # checking if to.user_id == pEp.PEP_OWN_USERID - # could lead to false positive depending on what pEpEngine - # consider to be its own identity - if to.address in own_addresses: - decrypt_result = msg.decrypt() - break + decrypt_result = msg.decrypt() + # TODO get status instead of an exception when consumed... + #if decrypt_result == 0xff02: #PEP_MESSAGE_CONSUMED + # msgs_for_me.pop(idx) + print(header()) res = None - if command is not None: - func = command[0] - args, kwargs = command[1:] + [[], {}][len(command) - 1:] - print(func, args, kwargs) + if func is not None: + print(header("Instance " + iname + " : function " + func.__name__)) + args, kwargs = order[1:] + [[], {}][len(order) - 1:] + print("args :", args) + print("kwargs :", kwargs) res = func(*args,**kwargs) - print(func, args, kwargs, " -> ", res) + print(" -> ", res) + print(header()) - conn.send([res, sent_messages]) - sent_messages = [] + conn.send(res) -def pEp_instance_main(iname, conn): +def pEp_instance_main(iname, conn, msgs_folders): # run with a dispensable $HOME to get fresh DB and PGP keyrings with tempfile.TemporaryDirectory() as tmpdirname: - print(iname + " instance runs into " + tmpdirname) + print("Instance " + iname + " runs into " + tmpdirname) os.environ['HOME'] = tmpdirname - pEp_instance_run(iname, conn) + pEp_instance_run(iname, conn, msgs_folders) print(iname + " exiting") def run_scenario(scenario): instances = OrderedDict() - for iname, order in scenario: - if iname not in instances: - to_inst_msg = [] - conn, child_conn = multiprocessing.Pipe() - proc = multiprocessing.Process(target=pEp_instance_main, args=(iname,child_conn)) - proc.start() - instances[iname] = (proc, conn, to_inst_msg) - else: - proc, conn, to_inst_msg = instances[iname] - - conn.send([order, to_inst_msg]) - res, from_inst_msgs = conn.recv() - - for iname, (proc, conn, to_inst_msg) in instances.items(): - # tell process to terminate - conn.send(None) - proc.join() + with multiprocessing.Manager() as manager: + msgs_folders = manager.dict() + for iname, order in scenario: + if iname not in instances: + conn, child_conn = multiprocessing.Pipe() + proc = multiprocessing.Process( + target=pEp_instance_main, + args=(iname,child_conn,msgs_folders)) + proc.start() + instances[iname] = (proc, conn) + else: + proc, conn = instances[iname] + + conn.send(order) + res = conn.recv() + + for iname, (proc, conn) in instances.items(): + # tell process to terminate + conn.send(None) + proc.join()