Component migration to use storage

!! Warning !! Not fully tested.

darcs-hash:20060122125943-86b55-a0cb0c408b0974b18af8613144bb3a7c3f2288bf.gz
This commit is contained in:
David Rousselie
2006-01-22 13:59:43 +01:00
parent edc1a693ae
commit a44b18828e
7 changed files with 269 additions and 256 deletions

View File

@@ -65,7 +65,6 @@ class MailComponent(Component):
self.__interval = int(config.get_content("config/check_interval")) self.__interval = int(config.get_content("config/check_interval"))
self.__config = config self.__config = config
# self.__registered = {}
try: try:
self.__storage = globals()[config.get_content("config/storage") + "Storage"]() self.__storage = globals()[config.get_content("config/storage") + "Storage"]()
except: except:
@@ -345,16 +344,17 @@ class MailComponent(Component):
finally: finally:
## TODO : for jid in self.__storage.keys(()) ## TODO : for jid in self.__storage.keys(())
## for name in self.__storage.keys((jid,)) ## for name in self.__storage.keys((jid,))
# for jid in self.__storage.keys(()): if self.stream:
# p = Presence(from_jid = str(self.jid), to_jid = jid, \ for jid in self.__storage.keys(()):
# stanza_type = "unavailable") p = Presence(from_jid = str(self.jid), to_jid = jid, \
# self.stream.send(p) stanza_type = "unavailable")
# for name in self.__registered[jid].keys(): self.stream.send(p)
# if self.__storage[(jid, name)].status != "offline": for jid, name in self.__storage.keys():
# p = Presence(from_jid = name + "@" + str(self.jid), \ if self.__storage[(jid, name)].status != "offline":
# to_jid = jid, \ p = Presence(from_jid = name + "@" + str(self.jid), \
# stanza_type = "unavailable") to_jid = jid, \
# self.stream.send(p) stanza_type = "unavailable")
self.stream.send(p)
threads = threading.enumerate() threads = threading.enumerate()
for th in threads: for th in threads:
try: try:
@@ -392,10 +392,14 @@ class MailComponent(Component):
def authenticated(self): def authenticated(self):
self.__logger.debug("AUTHENTICATED") self.__logger.debug("AUTHENTICATED")
Component.authenticated(self) Component.authenticated(self)
# for jid in self.__registered.keys(): for jid, name in self.__storage.keys():
# p = Presence(from_jid = str(self.jid), \ p = Presence(from_jid = name + "@" + str(self.jid), \
# to_jid = jid, stanza_type = "probe") to_jid = jid, stanza_type = "probe")
# self.stream.send(p) self.stream.send(p)
for jid in self.__storage.keys(()):
p = Presence(from_jid = str(self.jid), \
to_jid = jid, stanza_type = "probe")
self.stream.send(p)
self.stream.set_iq_get_handler("query", "jabber:iq:version", \ self.stream.set_iq_get_handler("query", "jabber:iq:version", \
self.get_version) self.get_version)
@@ -445,9 +449,9 @@ class MailComponent(Component):
self.__logger.debug("DISCO_GET_ITEMS") self.__logger.debug("DISCO_GET_ITEMS")
base_from_jid = str(iq.get_from().bare()) base_from_jid = str(iq.get_from().bare())
di = DiscoItems() di = DiscoItems()
if not node and self.__registered.has_key(base_from_jid): if not node:
for name in self.__registered[base_from_jid].keys(): for jid, name in self.__storage.keys():
account = self.__registered[base_from_jid][name] account = self.__storage[(jid, name)]
str_name = account.get_type() + " connection " + name str_name = account.get_type() + " connection " + name
if account.get_type()[0:4] == "imap": if account.get_type()[0:4] == "imap":
str_name += " (" + account.mailbox + ")" str_name += " (" + account.mailbox + ")"
@@ -488,8 +492,7 @@ class MailComponent(Component):
remove = iq.xpath_eval("r:query/r:remove", \ remove = iq.xpath_eval("r:query/r:remove", \
{"r" : "jabber:iq:register"}) {"r" : "jabber:iq:register"})
if remove: if remove:
if self.__registered.has_key(base_from_jid): for jid, name in self.__storage.keys():
for name in self.__registered[base_from_jid].keys():
p = Presence(from_jid = name + "@" + str(self.jid), \ p = Presence(from_jid = name + "@" + str(self.jid), \
to_jid = from_jid, \ to_jid = from_jid, \
stanza_type = "unsubscribe") stanza_type = "unsubscribe")
@@ -498,8 +501,7 @@ class MailComponent(Component):
to_jid = from_jid, \ to_jid = from_jid, \
stanza_type = "unsubscribed") stanza_type = "unsubscribed")
self.stream.send(p) self.stream.send(p)
del self.__registered[base_from_jid] del self.__storage[(jid, name)]
# self.__storage.
p = Presence(from_jid = self.jid, to_jid = from_jid, \ p = Presence(from_jid = self.jid, to_jid = from_jid, \
stanza_type = "unsubscribe") stanza_type = "unsubscribe")
self.stream.send(p) self.stream.send(p)
@@ -585,9 +587,8 @@ class MailComponent(Component):
iq = iq.make_result_response() iq = iq.make_result_response()
self.stream.send(iq) self.stream.send(iq)
if not self.__registered.has_key(base_from_jid): if not self.__storage.has_key((base_from_jid,)):
self.__registered[base_from_jid] = {} p = Presence(from_jid = self.jid, to_jid = base_from_jid, \
p = Presence(from_jid = self.jid, to_jid = from_jid.bare(), \
stanza_type="subscribe") stanza_type="subscribe")
self.stream.send(p) self.stream.send(p)
@@ -596,7 +597,7 @@ class MailComponent(Component):
socket = host + ":" + str(port) socket = host + ":" + str(port)
else: else:
socket = host socket = host
if self.__registered[base_from_jid].has_key(name): if self.__storage.has_key((base_from_jid, name)):
m = Message(from_jid = self.jid, to_jid = from_jid, \ m = Message(from_jid = self.jid, to_jid = from_jid, \
stanza_type = "message", \ stanza_type = "message", \
body = u"Updated %s connection '%s': Registered with "\ body = u"Updated %s connection '%s': Registered with "\
@@ -611,31 +612,28 @@ class MailComponent(Component):
% (type, name, login, password, socket)) % (type, name, login, password, socket))
self.stream.send(m) self.stream.send(m)
p = Presence(from_jid = name + "@" + str(self.jid), \ p = Presence(from_jid = name + "@" + str(self.jid), \
to_jid = from_jid.bare(), \ to_jid = base_from_jid, \
stanza_type="subscribe") stanza_type="subscribe")
self.stream.send(p) self.stream.send(p)
self.__registered[base_from_jid][name] = \ self.__storage[(base_from_jid, name)] = account = \
mailconnection_factory.get_new_mail_connection(type) mailconnection_factory.get_new_mail_connection(type)
self.__registered[base_from_jid][name].login = login account.login = login
self.__registered[base_from_jid][name].password = password account.password = password
self.__registered[base_from_jid][name].host = host account.host = host
self.__registered[base_from_jid][name].ffc_action = ffc_action account.ffc_action = ffc_action
self.__registered[base_from_jid][name].online_action = online_action account.online_action = online_action
self.__registered[base_from_jid][name].away_action = away_action account.away_action = away_action
self.__registered[base_from_jid][name].ea_action = ea_action account.ea_action = ea_action
self.__registered[base_from_jid][name].offline_action = offline_action account.offline_action = offline_action
account.interval = interval
if port: if port:
self.__registered[base_from_jid][name].port = port account.port = port
if interval:
self.__registered[base_from_jid][name].interval = interval
if type[0:4] == "imap": if type[0:4] == "imap":
self.__registered[base_from_jid][name].mailbox = mailbox account.mailbox = mailbox
self.__storage.add([base_from_jid, name], self.__registered[base_from_jid][name])
return 1 return 1
""" Handle presence availability """ """ Handle presence availability """
@@ -646,35 +644,25 @@ class MailComponent(Component):
name = stanza.get_to().node name = stanza.get_to().node
show = stanza.get_show() show = stanza.get_show()
self.__logger.debug("SHOW : " + str(show)) self.__logger.debug("SHOW : " + str(show))
if self.__registered.has_key(base_from_jid): if name:
if not name: self.__logger.debug("TO : " + name + " " + base_from_jid)
if not name and self.__storage.has_key((base_from_jid,)):
p = Presence(from_jid = self.jid, \ p = Presence(from_jid = self.jid, \
to_jid = from_jid, \ to_jid = from_jid, \
status = \ status = \
str(len(self.__registered[base_from_jid])) \ str(len(self.__storage.keys((base_from_jid,)))) \
+ " accounts registered.", \ + " accounts registered.", \
show = show, \ show = show, \
stanza_type = "available") stanza_type = "available")
self.stream.send(p) self.stream.send(p)
for name in self.__registered[base_from_jid].keys(): elif self.__storage.has_key((base_from_jid, name)):
account = self.__registered[base_from_jid][name] account = self.__storage[(base_from_jid, name)]
# Make available to receive mail only when online # Make available to receive mail only when online
account.status = "offline" # TODO get real status available = (not show) account.status = "online" # TODO get real status = (not show)
p = Presence(from_jid = name + "@" + \ p = Presence(from_jid = name + "@" + \
str(self.jid), \ str(self.jid), \
to_jid = from_jid, \ to_jid = from_jid, \
status = account.get_status(), \ status = account.get_status_msg(), \
show = show, \
stanza_type = "available")
self.stream.send(p)
elif self.__registered[base_from_jid].has_key(name):
account = self.__registered[base_from_jid][name]
# Make available to receive mail only when online
account.status = "offline" # TODO get real status = (not show)
p = Presence(from_jid = name + "@" + \
str(self.jid), \
to_jid = from_jid, \
status = account.get_status(), \
show = show, \ show = show, \
stanza_type = "available") stanza_type = "available")
self.stream.send(p) self.stream.send(p)
@@ -685,10 +673,9 @@ class MailComponent(Component):
self.__logger.debug("PRESENCE_UNAVAILABLE") self.__logger.debug("PRESENCE_UNAVAILABLE")
from_jid = stanza.get_from() from_jid = stanza.get_from()
base_from_jid = str(from_jid.bare()) base_from_jid = str(from_jid.bare())
if stanza.get_to() == str(self.jid) \ if stanza.get_to() == str(self.jid):
and self.__registered.has_key(base_from_jid): for jid, name in self.__storage.keys():
for name in self.__registered[base_from_jid].keys(): self.__storage[(base_from_jid, name)].status = "offline" # TODO get real status
self.__registered[base_from_jid][name].status = "offline" # TODO get real status
p = Presence(from_jid = name + "@" + str(self.jid), \ p = Presence(from_jid = name + "@" + str(self.jid), \
to_jid = from_jid, \ to_jid = from_jid, \
stanza_type = "unavailable") stanza_type = "unavailable")
@@ -712,12 +699,11 @@ class MailComponent(Component):
name = stanza.get_to().node name = stanza.get_to().node
from_jid = stanza.get_from() from_jid = stanza.get_from()
base_from_jid = str(from_jid.bare()) base_from_jid = str(from_jid.bare())
if self.__registered.has_key(base_from_jid) \ if name is not None and self.__storage.has_key((base_from_jid, name)):
and self.__registered[base_from_jid].has_key(name): account = self.__storage[(base_from_jid, name)]
account = self.__registered[base_from_jid][name]
account.status = "online" # TODO retrieve real status account.status = "online" # TODO retrieve real status
p = Presence(from_jid = stanza.get_to(), to_jid = from_jid, \ p = Presence(from_jid = stanza.get_to(), to_jid = from_jid, \
status = account.get_status(), \ status = account.get_status_msg(), \
stanza_type = "available") stanza_type = "available")
self.stream.send(p) self.stream.send(p)
return 1 return 1
@@ -728,9 +714,8 @@ class MailComponent(Component):
name = stanza.get_to().node name = stanza.get_to().node
from_jid = stanza.get_from() from_jid = stanza.get_from()
base_from_jid = str(from_jid.bare()) base_from_jid = str(from_jid.bare())
if self.__registered.has_key(base_from_jid) \ if name is not None and self.__storage.has_key((base_from_jid, name)):
and self.__registered[base_from_jid].has_key(name): del self.__storage[(base_from_jid, name)]
del self.__registered[base_from_jid][name]
p = Presence(from_jid = stanza.get_to(), to_jid = from_jid, \ p = Presence(from_jid = stanza.get_to(), to_jid = from_jid, \
stanza_type = "unsubscribe") stanza_type = "unsubscribe")
self.stream.send(p) self.stream.send(p)
@@ -752,20 +737,20 @@ class MailComponent(Component):
self.__logger.debug("MESSAGE: " + message.get_body()) self.__logger.debug("MESSAGE: " + message.get_body())
name = message.get_to().node name = message.get_to().node
base_from_jid = str(message.get_from().bare()) base_from_jid = str(message.get_from().bare())
if name and self.__registered.has_key(base_from_jid): # if name and self.__registered.has_key(base_from_jid):
body = message.get_body() # body = message.get_body()
cmd = body.split(' ') # cmd = body.split(' ')
if cmd[0] == "check": # if cmd[0] == "check":
self.check_mail(base_from_jid, name) # self.check_mail(base_from_jid, name)
elif cmd[0] == "dump": # elif cmd[0] == "dump":
body = "" # body = ""
for jid in self.__registered.keys(): # for jid in self.__registered.keys():
for name in self.__registered[jid].keys(): # for name in self.__registered[jid].keys():
body += name + " for user " + jid # body += name + " for user " + jid
msg = Message(from_jid = self.jid, to_jid = base_from_jid, \ # msg = Message(from_jid = self.jid, to_jid = base_from_jid, \
stanza_type = "message", \ # stanza_type = "message", \
body = body) # body = body)
self.stream.send(msg) # self.stream.send(msg)
return 1 return 1
# """ Store registered sessions """ # """ Store registered sessions """
@@ -863,6 +848,7 @@ class MailComponent(Component):
""" check mail handler """ """ check mail handler """
def check_all_mail(self): def check_all_mail(self):
self.__logger.debug("CHECK_ALL_MAIL") self.__logger.debug("CHECK_ALL_MAIL")
for jid in self.__registered.keys(): ## TODO
for name in self.__registered[jid].keys(): # for jid in self.__registered.keys():
self.check_mail(jid, name) # for name in self.__registered[jid].keys():
# self.check_mail(jid, name)

View File

@@ -156,6 +156,7 @@ class MailConnection(object):
self.away_action = RETRIEVE self.away_action = RETRIEVE
self.ea_action = RETRIEVE self.ea_action = RETRIEVE
self.offline_action = DO_NOTHING self.offline_action = DO_NOTHING
self.interval = 5
def __eq__(self, other): def __eq__(self, other):
return self.get_type() == other.get_type() \ return self.get_type() == other.get_type() \
@@ -168,7 +169,8 @@ class MailConnection(object):
and self.online_action == other.online_action \ and self.online_action == other.online_action \
and self.away_action == other.away_action \ and self.away_action == other.away_action \
and self.ea_action == other.ea_action \ and self.ea_action == other.ea_action \
and self.offline_action == other.offline_action and self.offline_action == other.offline_action \
and self.interval == other.interval
def __str__(self): def __str__(self):
return self.get_type() + "#" + self.login + "#" + self.password + "#" \ return self.get_type() + "#" + self.login + "#" + self.password + "#" \
@@ -219,7 +221,7 @@ class MailConnection(object):
def get_type(self): def get_type(self):
return "UNKNOWN" return "UNKNOWN"
def get_status(self): def get_status_msg(self):
return self.get_type() + "://" + self.login + "@" + self.host + ":" + \ return self.get_type() + "://" + self.login + "@" + self.host + ":" + \
str(self.port) str(self.port)
@@ -246,7 +248,7 @@ class MailConnection(object):
"offline": self.offline_action} "offline": self.offline_action}
if mapping.has_key(self.status): if mapping.has_key(self.status):
return mapping[self.status] return mapping[self.status]
return "nothing" return NOTHING
action = property(get_action) action = property(get_action)

View File

@@ -66,38 +66,29 @@ class DBMStorage(Storage):
def __init__(self, nb_pk_fields = 1, spool_dir = "."): def __init__(self, nb_pk_fields = 1, spool_dir = "."):
# print "DBM INIT" # print "DBM INIT"
Storage.__init__(self, nb_pk_fields, spool_dir) Storage.__init__(self, nb_pk_fields, spool_dir)
self.__str_registered = anydbm.open(self.file, \ self.__registered = self.load()
'c')
def __del__(self): def __del__(self):
# print "DBM STOP" # print "DBM STOP"
self.__str_registered.close() self.sync()
def load(self): def load(self):
# print "DBM LOAD" # print "DBM LOAD"
str_registered = anydbm.open(self.file, \
'c')
result = {} result = {}
try: try:
for pk in self.__str_registered.keys(): for pk in str_registered.keys():
pk_list = pk.split('#') result[pk] = mailconnection_factory.str_to_mail_connection(str_registered[pk])
obj = result
key = None
while pk_list:
key = pk_list.pop(0)
if pk_list:
if not obj.has_key(key):
obj[key] = {}
obj = obj[key]
obj[key] = mailconnection_factory.str_to_mail_connection(self.__str_registered[pk])
except Exception, e: except Exception, e:
print >>sys.stderr, "Cannot load registered.db : " print >>sys.stderr, "Cannot load registered.db : "
print >>sys.stderr, e print >>sys.stderr, e
str_registered.close()
return result return result
def sync(self): def sync(self):
# print "DBM SYNC" # print "DBM SYNC"
self.__str_registered.close() self.store()
self.__str_registered = anydbm.open(self.file, \
'c')
def __store(self, nb_pk_fields, registered, pk): def __store(self, nb_pk_fields, registered, pk):
if nb_pk_fields > 0: if nb_pk_fields > 0:
@@ -112,53 +103,69 @@ class DBMStorage(Storage):
self.__str_registered[pk] = str(registered) self.__str_registered[pk] = str(registered)
print "STORING : " + pk + " = " + str(registered) print "STORING : " + pk + " = " + str(registered)
def store(self, registered): def store(self):
# print "DBM STORE" # print "DBM STORE"
try: try:
self.__store(self.nb_pk_fields, registered, "") str_registered = anydbm.open(self.file, \
# Force file synchronisation 'c')
self.sync() for pk in self.__registered.keys():
str_registered[pk] = str(self.__registered[pk])
except Exception, e: except Exception, e:
print >>sys.stderr, "Cannot save to registered.db : " print >>sys.stderr, "Cannot save to registered.db : "
print >>sys.stderr, e print >>sys.stderr, e
str_registered.close()
def __setitem__(self, pk_tuple, obj): def __setitem__(self, pk_tuple, obj):
# print "Adding " + "#".join(pk_tuple) + " = " + str(obj) # print "Adding " + "#".join(pk_tuple) + " = " + str(obj)
self.__str_registered["#".join(pk_tuple)] = str(obj) self.__registered[str("#".join(pk_tuple))] = obj
self.sync() self.sync()
def __getitem__(self, pk_tuple): def __getitem__(self, pk_tuple):
# print "Getting " + "#".join(pk_tuple) # print "Getting " + "#".join(pk_tuple)
if len(pk_tuple) == self.nb_pk_fields: if len(pk_tuple) == self.nb_pk_fields:
return mailconnection_factory.str_to_mail_connection(self.__str_registered["#".join(pk_tuple)]) return self.__registered[str("#".join(pk_tuple))]
else: else:
partial_key = "#".join(pk_tuple) partial_key = str("#".join(pk_tuple))
regexp = re.compile(partial_key) regexp = re.compile(partial_key)
return [mailconnection_factory.str_to_mail_connection(self.__str_registered[key]) return [self.__registered[key]
for key in self.__str_registered.keys() for key in self.__registered.keys()
if regexp.search(key)] if regexp.search(key)]
def __delitem__(self, pk_tuple): def __delitem__(self, pk_tuple):
# print "Deleting " + "#".join(pk_tuple) # print "Deleting " + "#".join(pk_tuple)
del self.__str_registered["#".join(pk_tuple)] del self.__registered[str("#".join(pk_tuple))]
self.sync() self.sync()
def has_key(self, pk_tuple): def has_key(self, pk_tuple):
return self.__str_registered.has_key("#".join(pk_tuple)) if len(pk_tuple) == self.nb_pk_fields:
return self.__registered.has_key(str("#".join(pk_tuple)))
else:
partial_key = str("#".join(pk_tuple))
regexp = re.compile("^" + partial_key)
for key in self.__registered.keys():
if regexp.search(key):
return True
return False
def keys(self, pk_tuple = None): def keys(self, pk_tuple = None):
if pk_tuple is None: if pk_tuple is None:
return [tuple(key.split("#")) for key in self.__str_registered.keys()] return [tuple(key.split("#")) for key in self.__registered.keys()]
else: else:
level = len(pk_tuple) level = len(pk_tuple)
partial_key = "#".join(pk_tuple) partial_key = str("#".join(pk_tuple))
regexp = re.compile("^" + partial_key) regexp = re.compile("^" + partial_key)
result = {} result = {}
for key in self.__str_registered.keys(): for key in self.__registered.keys():
if regexp.search(key): if regexp.search(key):
result[key.split("#")[level]] = None result[key.split("#")[level]] = None
return result.keys() return result.keys()
def dump(self):
print "dumping"
for pk in self.__registered.keys():
print pk + " = " + str(self.__registered[pk])
class SQLiteStorage(Storage): class SQLiteStorage(Storage):
def __init__(self, nb_pk_fields = 1, spool_dir = "."): def __init__(self, nb_pk_fields = 1, spool_dir = "."):
pass pass

View File

@@ -32,8 +32,12 @@ from tests.test_component import *
from tests.test_storage import * from tests.test_storage import *
from test import test_support from test import test_support
import jabber import jabber
import logging
if __name__ == '__main__': if __name__ == '__main__':
logger = logging.getLogger()
logger.addHandler(logging.StreamHandler())
logger.setLevel(logging.INFO)
mail_connection_suite = unittest.makeSuite(MailConnection_TestCase, \ mail_connection_suite = unittest.makeSuite(MailConnection_TestCase, \
"test") "test")
pop3_connection_suite = unittest.makeSuite(POP3Connection_TestCase, \ pop3_connection_suite = unittest.makeSuite(POP3Connection_TestCase, \
@@ -59,7 +63,7 @@ if __name__ == '__main__':
component2_suite, \ component2_suite, \
storage_suite, \ storage_suite, \
dbmstorage_suite)) dbmstorage_suite))
test_support.run_suite(component2_suite) test_support.run_suite(storage_suite)
# coverage.stop() # coverage.stop()
# coverage.analysis(jabber.mailconnection_factory) # coverage.analysis(jabber.mailconnection_factory)

View File

@@ -55,9 +55,6 @@ class DummyServer:
self.queries = None self.queries = None
self.real_queries = [] self.real_queries = []
def __del__(self):
self.socket.close()
def serve(self): def serve(self):
conn, addr = self.socket.accept() conn, addr = self.socket.accept()
rfile = conn.makefile('rb', -1) rfile = conn.makefile('rb', -1)
@@ -80,6 +77,8 @@ class DummyServer:
self.real_queries.append(data) self.real_queries.append(data)
# print >>sys.stderr, 'Receive : ', data # print >>sys.stderr, 'Receive : ', data
conn.close() conn.close()
self.socket.close()
self.socket = None
def verify_queries(self): def verify_queries(self):
result = True result = True
@@ -114,8 +113,10 @@ class XMLDummyServer(DummyServer):
# TODO : this approximation is not clean # TODO : this approximation is not clean
# received size is based on the expected size in self.queries # received size is based on the expected size in self.queries
data = conn.recv(1024 + len(self.queries[idx])) data = conn.recv(1024 + len(self.queries[idx]))
print "receive : " + data
if data: if data:
# print "-----------RECEIVE " + data ## TODO : without this log, test_set_register in test_component wait forever
#print "-----------RECEIVE1 " + data
r = self._reader.feed(data) r = self._reader.feed(data)
except: except:
type, value, stack = sys.exc_info() type, value, stack = sys.exc_info()
@@ -132,9 +133,16 @@ class XMLDummyServer(DummyServer):
else: else:
response = self.responses[idx] response = self.responses[idx]
if response is not None: if response is not None:
# print >>sys.stderr, '---------SENDING : ', response print >>sys.stderr, '---------SENDING : ', response
conn.send(response) conn.send(response)
data = conn.recv(1024)
if data:
print "-----------RECEIVE2 " + data
r = self._reader.feed(data)
self.real_queries.append(data)
conn.close() conn.close()
self.socket.close()
self.socket = None
except: except:
type, value, stack = sys.exc_info() type, value, stack = sys.exc_info()
print "".join (traceback.format_exception print "".join (traceback.format_exception
@@ -143,15 +151,14 @@ class XMLDummyServer(DummyServer):
def verify_queries(self): def verify_queries(self):
result = True result = True
queries_len = len(self.queries)
if queries_len == len(self.real_queries):
full_real_queries = "" full_real_queries = ""
full_recv_queries = "" full_recv_queries = ""
for idx in range(queries_len): for idx in range(len(self.real_queries)):
full_real_queries += self.real_queries[idx].rstrip(os.linesep) full_real_queries += self.real_queries[idx].rstrip(os.linesep)
full_recv_queries += self.queries[idx].rstrip(os.linesep) full_recv_queries += self.queries[idx].rstrip(os.linesep)
# Do not receive it but add it so that xml parsing can succeed # Do not receive it but add it so that xml parsing can succeed
full_real_queries += "</stream:stream>" #full_real_queries += "</stream:stream>"
print full_real_queries
real_query = xml.dom.minidom.parseString(full_real_queries) real_query = xml.dom.minidom.parseString(full_real_queries)
recv_query = xml.dom.minidom.parseString(full_recv_queries) recv_query = xml.dom.minidom.parseString(full_recv_queries)
try: try:
@@ -159,10 +166,6 @@ class XMLDummyServer(DummyServer):
except Exception, msg: except Exception, msg:
result = False result = False
print >>sys.stderr, msg print >>sys.stderr, msg
else:
result = False
print >>sys.stderr, "Expected " + str(queries_len) + \
" queries, got " + str(len(self.real_queries))
return result return result
def test(): def test():

View File

@@ -66,12 +66,14 @@ class MailComponent_TestCase_Basic(unittest.TestCase):
def tearDown(self): def tearDown(self):
self.server = None self.server = None
self.mail_component = None self.mail_component = None
os.remove("./registered.db")
def test_run(self): def test_run(self):
self.server.responses = ["<?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:component:accept' id='4258238724' from='localhost'>", \ self.server.responses = ["<?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:component:accept' id='4258238724' from='localhost'>", \
"<handshake/></stream:stream>"] "<handshake/></stream:stream>"]
self.server.queries = ["<?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:component:accept' to='jmc.localhost' version='1.0'>", \ self.server.queries = ["<?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:component:accept' to='jmc.localhost' version='1.0'>", \
"<handshake>[0-9abcdef]*</handshake></stream:stream>"] "<handshake>[0-9abcdef]*</handshake>",
"</stream:stream>"]
self.mail_component.run(1) self.mail_component.run(1)
self.failUnless(self.server.verify_queries()) self.failUnless(self.server.verify_queries())
# TODO : more assertion # TODO : more assertion
@@ -79,9 +81,6 @@ class MailComponent_TestCase_Basic(unittest.TestCase):
class MailComponent_TestCase_NoReg(unittest.TestCase): class MailComponent_TestCase_NoReg(unittest.TestCase):
def setUp(self): def setUp(self):
self.handler = TestStreamHandler() self.handler = TestStreamHandler()
# logger = logging.getLogger()
# logger.addHandler(logging.StreamHandler())
# logger.setLevel(logging.DEBUG)
self.mail_component = MailComponent(Config("tests/jmc-test.xml")) self.mail_component = MailComponent(Config("tests/jmc-test.xml"))
self.server = dummy_server.XMLDummyServer("localhost", 55555, None, self.handler) self.server = dummy_server.XMLDummyServer("localhost", 55555, None, self.handler)
thread.start_new_thread(self.server.serve, ()) thread.start_new_thread(self.server.serve, ())
@@ -89,25 +88,28 @@ class MailComponent_TestCase_NoReg(unittest.TestCase):
def tearDown(self): def tearDown(self):
self.server = None self.server = None
self.mail_component = None self.mail_component = None
## TODO : be storage independant
os.remove("./registered.db")
def test_disco_get_items(self): def test_disco_get_items(self):
self.server.responses = ["<?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:component:accept' id='4258238724' from='localhost'>", \ self.server.responses = ["<?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:component:accept' id='4258238724' from='localhost'>",
"<handshake/><iq type='get' to='jmc.localhost' id='aabca'><query xmlns='http://jabber.org/protocol/disco#info'/></iq>", \ "<handshake/><iq type='get' to='jmc.localhost' id='aabca'><query xmlns='http://jabber.org/protocol/disco#info'/></iq>",
"</stream:stream>"] "</stream:stream>"]
self.server.queries = ["<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + \ self.server.queries = ["<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + \
"<stream:stream xmlns:stream=\"http://etherx.jabber.org/streams\" xmlns=\"jabber:component:accept\" to=\"jmc.localhost\" version=\"1.0\">", \ "<stream:stream xmlns:stream=\"http://etherx.jabber.org/streams\" xmlns=\"jabber:component:accept\" to=\"jmc.localhost\" version=\"1.0\">", \
"<handshake>[0-9abcdef]*</handshake>", \ "<handshake>[0-9abcdef]*</handshake>",
"<iq from=\"jmc.localhost\" type=\"result\" id=\"aabca\"><query xmlns=\"http://jabber.org/protocol/disco#info\"><feature var=\"jabber:iq:version\"/><feature var=\"jabber:iq:register\"/><identity name=\"Jabber Mail Component\" category=\"headline\" type=\"mail\"/></query></iq></stream:stream>"] "<iq from=\"jmc.localhost\" type=\"result\" id=\"aabca\"><query xmlns=\"http://jabber.org/protocol/disco#info\"><feature var=\"jabber:iq:version\"/><feature var=\"jabber:iq:register\"/><identity name=\"Jabber Mail Component\" category=\"headline\" type=\"mail\"/></query></iq>",
"</stream:stream>"]
self.mail_component.run(1) self.mail_component.run(1)
self.failUnless(self.server.verify_queries()) self.failUnless(self.server.verify_queries())
def test_get_register(self): def test_get_register(self):
self.server.responses = ["<?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:component:accept' id='4258238724' from='localhost'>", \ self.server.responses = ["<?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:component:accept' id='4258238724' from='localhost'>",
"<handshake/><iq type='get' to='jmc.localhost' from='test@localhost/test' id='aad9a'><query xmlns='jabber:iq:register'/></iq>", \ "<handshake/><iq type='get' to='jmc.localhost' from='test@localhost/test' id='aad9a'><query xmlns='jabber:iq:register'/></iq>",
"</stream:stream>"] "</stream:stream>"]
self.server.queries = ["<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + \ self.server.queries = ["<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + \
"<stream:stream xmlns:stream=\"http://etherx.jabber.org/streams\" xmlns=\"jabber:component:accept\" to=\"jmc.localhost\" version=\"1.0\">", \ "<stream:stream xmlns:stream=\"http://etherx.jabber.org/streams\" xmlns=\"jabber:component:accept\" to=\"jmc.localhost\" version=\"1.0\">", \
"<handshake>[0-9abcdef]*</handshake>", \ "<handshake>[0-9abcdef]*</handshake>",
"<iq from=\"jmc.localhost\" to=\"test@localhost/test\" type=\"result\" id=\"aad9a\">" + \ "<iq from=\"jmc.localhost\" to=\"test@localhost/test\" type=\"result\" id=\"aad9a\">" + \
"<query xmlns=\"jabber:iq:register\">" + \ "<query xmlns=\"jabber:iq:register\">" + \
"<x xmlns=\"jabber:x:data\">" + \ "<x xmlns=\"jabber:x:data\">" + \
@@ -200,84 +202,90 @@ class MailComponent_TestCase_NoReg(unittest.TestCase):
"</field>" + \ "</field>" + \
"</x>" + \ "</x>" + \
"</query>" + \ "</query>" + \
"</iq>" + \ "</iq>",
"</stream:stream>"] "</stream:stream>"]
self.mail_component.run(1) self.mail_component.run(1)
self.failUnless(self.server.verify_queries()) self.failUnless(self.server.verify_queries())
def test_disco_get_info(self): def test_disco_get_info(self):
self.server.responses = ["<?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:component:accept' id='4258238724' from='localhost'>", \ self.server.responses = ["<?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:component:accept' id='4258238724' from='localhost'>",
"<handshake/><iq type='get' to='jmc.localhost' from='test@localhost/test' id='aad9a'><query xmlns='http://jabber.org/protocol/disco#info'/></iq>", \ "<handshake/><iq type='get' to='jmc.localhost' from='test@localhost/test' id='aad9a'><query xmlns='http://jabber.org/protocol/disco#info'/></iq>",
"</stream:stream>"] "</stream:stream>"]
self.server.queries = ["<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + \ self.server.queries = ["<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + \
"<stream:stream xmlns:stream=\"http://etherx.jabber.org/streams\" xmlns=\"jabber:component:accept\" to=\"jmc.localhost\" version=\"1.0\">", \ "<stream:stream xmlns:stream=\"http://etherx.jabber.org/streams\" xmlns=\"jabber:component:accept\" to=\"jmc.localhost\" version=\"1.0\">",
"<handshake>[0-9abcdef]*</handshake>", \ "<handshake>[0-9abcdef]*</handshake>",
"<iq from=\"jmc.localhost\" to=\"test@localhost/test\" type=\"result\" id=\"aad9a\">" + \ "<iq from=\"jmc.localhost\" to=\"test@localhost/test\" type=\"result\" id=\"aad9a\">" + \
"<query xmlns=\"http://jabber.org/protocol/disco#info\">" + \ "<query xmlns=\"http://jabber.org/protocol/disco#info\">" + \
"<feature var=\"jabber:iq:version\"/>" + \ "<feature var=\"jabber:iq:version\"/>" + \
"<feature var=\"jabber:iq:register\"/>" + \ "<feature var=\"jabber:iq:register\"/>" + \
"<identity name=\"Jabber Mail Component\" category=\"headline\" type=\"mail\"/>" + \ "<identity name=\"Jabber Mail Component\" category=\"headline\" type=\"mail\"/>" + \
"</query></iq>" + \ "</query></iq>",
"</stream:stream>"] "</stream:stream>"]
self.mail_component.run(1) self.mail_component.run(1)
self.failUnless(self.server.verify_queries()) self.failUnless(self.server.verify_queries())
# def test_set_register(self): def test_set_register(self):
# self.server.responses = ["<?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:component:accept' id='4258238724' from='localhost'>", \ self.server.responses = ["<?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:component:accept' id='4258238724' from='localhost'>", \
# "<handshake/>" + \ "<handshake/>" + \
# "<iq from='test@localhost/test' to='jmc.localhost' type='set' id='aacaa'>" + \ "<iq from='test@localhost/test' to='jmc.localhost' type='set' id='aacaa'>" + \
# "<query xmlns='jabber:iq:register'>" + \ "<query xmlns='jabber:iq:register'>" + \
# "<x xmlns='jabber:x:data' type='submit'>" + \ "<x xmlns='jabber:x:data' type='submit'>" + \
# "<field type='text-single' var='name'>" + \ "<field type='text-single' var='name'>" + \
# "<value>test</value>" + \ "<value>test</value>" + \
# "</field>" + \ "</field>" + \
# "<field type='text-single' var='login'>" + \ "<field type='text-single' var='login'>" + \
# "<value>logintest</value>" + \ "<value>logintest</value>" + \
# "</field>" + \ "</field>" + \
# "<field type='text-private' var='password'>" + \ "<field type='text-private' var='password'>" + \
# "<value>passtest</value>" + \ "<value>passtest</value>" + \
# "</field>" + \ "</field>" + \
# "<field type='text-single' var='host'>" + \ "<field type='text-single' var='host'>" + \
# "<value>hosttest</value>" + \ "<value>hosttest</value>" + \
# "</field>" + \ "</field>" + \
# "<field type='text-single' var='port'>" + \ "<field type='text-single' var='port'>" + \
# "<value>993</value>" + \ "<value>993</value>" + \
# "</field>" + \ "</field>" + \
# "<field type='list-single' var='type'>" + \ "<field type='list-single' var='type'>" + \
# "<value>imaps</value>" + \ "<value>imaps</value>" + \
# "</field>" + \ "</field>" + \
# "<field type='text-single' var='mailbox'>" + \ "<field type='text-single' var='mailbox'>" + \
# "<value>INBOX</value>" + \ "<value>INBOX</value>" + \
# "</field>" + \ "</field>" + \
# "<field type='list-single' var='ffc_action'>" + \ "<field type='list-single' var='ffc_action'>" + \
# "<value>2</value>" + \ "<value>2</value>" + \
# "</field>" + \ "</field>" + \
# "<field type='list-single' var='online_action'>" + \ "<field type='list-single' var='online_action'>" + \
# "<value>2</value>" + \ "<value>2</value>" + \
# "</field>" + \ "</field>" + \
# "<field type='list-single' var='away_action'>" + \ "<field type='list-single' var='away_action'>" + \
# "<value>1</value>" + \ "<value>1</value>" + \
# "</field>" + \ "</field>" + \
# "<field type='list-single' var='ea_action'>" + \ "<field type='list-single' var='ea_action'>" + \
# "<value>1</value>" + \ "<value>1</value>" + \
# "</field>" + \ "</field>" + \
# "<field type='list-single' var='offline_action'>" + \ "<field type='list-single' var='offline_action'>" + \
# "<value>0</value>" + \ "<value>0</value>" + \
# "</field>" + \ "</field>" + \
# "<field type='text-single' var='interval'>" + \ "<field type='text-single' var='interval'>" + \
# "<value>5</value>" + \ "<value>5</value>" + \
# "</field>" + \ "</field>" + \
# "</x>" + \ "</x>" + \
# "</query></iq>" + \ "</query></iq>",
# "<stream:stream>"] lambda x: None,
# self.server.queries = ["<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + \ lambda x: None,
# "<stream:stream xmlns:stream=\"http://etherx.jabber.org/streams\" xmlns=\"jabber:component:accept\" to=\"jmc.localhost\" version=\"1.0\">", \ lambda x: None,
# "<handshake>[0-9abcdef]*</handshake>", \ "</stream:stream>"]
# "<iq from=\"jmc.localhost\" to=\"test@localhost/Psi\" type=\"result\" id=\"aacaa\"/>", self.server.queries = ["<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + \
# "<stream:stream>"] "<stream:stream xmlns:stream=\"http://etherx.jabber.org/streams\" xmlns=\"jabber:component:accept\" to=\"jmc.localhost\" version=\"1.0\">", \
# self.mail_component.run(1) "<handshake>[0-9abcdef]*</handshake>", \
# self.failUnless(self.server.verify_queries()) "<iq from=\"jmc.localhost\" to=\"test@localhost/test\" type=\"result\" id=\"aacaa\"/>",
"<presence from=\"jmc.localhost\" to=\"test@localhost\" type=\"subscribe\"/>",
"<message from=\"jmc.localhost\" to=\"test@localhost/test\" type=\"message\"><body>New imaps connection \\'test\\': Registered with username \\'logintest\\' and password \\'passtest\\' on \\'hosttest:993\\'</body></message>",
"<presence from=\"test@jmc.localhost\" to=\"test@localhost\" type=\"subscribe\"/>",
"</stream:stream>"]
self.mail_component.run(1)
self.failUnless(self.server.verify_queries())
class MailComponent_TestCase_Reg(unittest.TestCase): class MailComponent_TestCase_Reg(unittest.TestCase):
def setUp(self): def setUp(self):

View File

@@ -97,8 +97,11 @@ class DBMStorage_TestCase(unittest.TestCase):
def test_haskey(self): def test_haskey(self):
self._storage[("test@localhost", "account2")] = self._account2 self._storage[("test@localhost", "account2")] = self._account2
self.assertTrue(self._storage.has_key(("test@localhost", "account2"))) self.assertTrue(self._storage.has_key((u"test@localhost", u"account2")))
def test_partial_haskey(self):
self._storage[("test@localhost", "account2")] = self._account2
self.assertTrue(self._storage.has_key((u"test@localhost",)))
def test_get_filtered(self): def test_get_filtered(self):
self._storage[("test@localhost", "account1")] = self._account1 self._storage[("test@localhost", "account1")] = self._account1
@@ -106,8 +109,8 @@ class DBMStorage_TestCase(unittest.TestCase):
result = self._storage[("test@localhost",)] result = self._storage[("test@localhost",)]
self.assertEquals(type(result), list) self.assertEquals(type(result), list)
self.assertEquals(len(result), 2) self.assertEquals(len(result), 2)
self.assertEquals(result[0], self._account1) self.assertEquals(result[1], self._account1)
self.assertEquals(result[1], self._account2) self.assertEquals(result[0], self._account2)
def test_get_filtered2(self): def test_get_filtered2(self):
self._storage[("test@localhost", "account1")] = self._account1 self._storage[("test@localhost", "account1")] = self._account1
@@ -123,14 +126,14 @@ class DBMStorage_TestCase(unittest.TestCase):
result = self._storage.keys() result = self._storage.keys()
self.assertEquals(type(result), list) self.assertEquals(type(result), list)
self.assertEquals(len(result), 2) self.assertEquals(len(result), 2)
self.assertEquals(type(result[0]), tuple)
self.assertEquals(len(result[0]), 2)
self.assertEquals(result[0][0], "test@localhost")
self.assertEquals(result[0][1], "account1")
self.assertEquals(type(result[1]), tuple) self.assertEquals(type(result[1]), tuple)
self.assertEquals(len(result[1]), 2) self.assertEquals(len(result[1]), 2)
self.assertEquals(result[1][0], "test@localhost") self.assertEquals(result[1][0], "test@localhost")
self.assertEquals(result[1][1], "account2") self.assertEquals(result[1][1], "account1")
self.assertEquals(type(result[0]), tuple)
self.assertEquals(len(result[0]), 2)
self.assertEquals(result[0][0], "test@localhost")
self.assertEquals(result[0][1], "account2")
def test_keys_filtered(self): def test_keys_filtered(self):
self._storage[("test@localhost", "account1")] = self._account1 self._storage[("test@localhost", "account1")] = self._account1