import threading import time import logging import argparse from twisted.internet import reactor from util import log from couchdb_server import get_couchdb_wrapper_and_u1db from mx import put_lots_of_messages from soledad_server import get_soledad_server from soledad_client import SoledadClient from mail import get_imap_server UUID = 'blah' AUTH_TOKEN = 'bleh' logging.basicConfig(level=logging.DEBUG) modules = [ 'gnupg', 'leap.common', 'leap.keymanager', 'taskthread', ] for module in modules: logger = logging.getLogger(name=module) logger.setLevel(logging.WARNING) class TestWatcher(threading.Thread): def __init__(self, couchdb_wrapper, couchdb_u1db, soledad_server, soledad_client, imap_service, number_of_msgs, lock): threading.Thread.__init__(self) self._couchdb_wrapper = couchdb_wrapper self._couchdb_u1db = couchdb_u1db self._soledad_server = soledad_server self._soledad_client = soledad_client self._imap_service = imap_service self._number_of_msgs = number_of_msgs self._lock = lock self._mails_available_time = None self._mails_available_time_lock = threading.Lock() self._conditions = None def run(self): self._set_conditions() while not self._test_finished(): time.sleep(5) log("TestWatcher: Tests finished, cleaning up...", line_break=False) self._stop_reactor() self._cleanup() log("done.") self._lock.release() def _set_conditions(self): self._conditions = [] # condition 1: number of received messages is equal to number of # expected messages def _condition1(*args): msgcount = self._imap_service._inbox.getMessageCount() cond = msgcount == self._number_of_msgs log("[condition 1] received messages: %d (expected: %d) :: %s" % (msgcount, self._number_of_msgs, cond)) if self.mails_available_time == None \ and cond: with self._mails_available_time_lock: self._mails_available_time = time.time() return cond # condition 2: number of documents in server is equal to in client def _condition2(client_docs, server_docs): cond = client_docs == server_docs log("[condition 2] number of documents: client %d; server %d :: %s" % (client_docs, server_docs, cond)) return cond # condition 3: number of documents bigger than 3 x number of msgs def _condition3(client_docs, *args): cond = client_docs > (2 * self._number_of_msgs) log("[condition 3] documents (%d) > 2 * msgs (%d) :: %s" % (client_docs, self._number_of_msgs, cond)) return cond # condition 4: not syncing def _condition4(*args): cond = not self._soledad_client.instance.syncing log("[condition 4] not syncing :: %s" % cond) return cond self._conditions.append(_condition1) self._conditions.append(_condition2) self._conditions.append(_condition3) self._conditions.append(_condition4) def _test_finished(self): client_docs = self._get_soledad_client_number_of_docs() server_docs = self._get_couchdb_number_of_docs() return not bool(filter(lambda x: not x(client_docs, server_docs), self._conditions)) def _stop_reactor(self): reactor.stop() def _cleanup(self): self._imap_service.stop() self._soledad_client.close() self._soledad_server.stop() self._couchdb_wrapper.stop() def _get_soledad_client_number_of_docs(self): c = self._soledad_client.instance._db._db_handle.cursor() c.execute('SELECT COUNT(*) FROM document WHERE content IS NOT NULL') row = c.fetchone() return int(row[0]) def _get_couchdb_number_of_docs(self): couchdb = self._couchdb_u1db._database view = couchdb.view('_all_docs', include_docs=True) return len(filter( lambda r: '_attachments' in r.values()[1] and 'u1db_content' in r.values()[1]['_attachments'], view.rows)) @property def mails_available_time(self): with self._mails_available_time_lock: return self._mails_available_time if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('number_of_msgs', help="The number of documents", type=int) parser.add_argument('report_file', help="The name of the report file", type=str) args = parser.parse_args() # start a couchdb server couchdb_wrapper, couchdb_u1db = get_couchdb_wrapper_and_u1db( UUID, AUTH_TOKEN) put_time = put_lots_of_messages(couchdb_u1db, args.number_of_msgs) soledad_server = get_soledad_server(couchdb_wrapper.port) soledad_client = SoledadClient( uuid='blah', server_url='http://127.0.0.1:%d' % soledad_server.port, auth_token=AUTH_TOKEN) imap_service = get_imap_server( soledad_client.instance, UUID, 'snowden@bitmask.net', AUTH_TOKEN) lock = threading.Lock() lock.acquire() test_watcher = TestWatcher( couchdb_wrapper, couchdb_u1db, soledad_server, soledad_client, imap_service, args.number_of_msgs, lock) test_watcher.start() # reactor.run() will block until TestWatcher stops the reactor. start_time = time.time() reactor.run() log("Reactor stopped.") end_time = time.time() lock.acquire() mails_available_time = test_watcher.mails_available_time - start_time sync_time = end_time - start_time log("Total syncing time: %f" % sync_time) log("# number_of_msgs put_time mails_available_time sync_time") result = "%d %f %f %f" \ % (args.number_of_msgs, put_time, mails_available_time, sync_time) log(result) with open(args.report_file, 'a') as f: f.write(result + "\n")