Commit 4db74aeb authored by Sebastien Robin's avatar Sebastien Robin

- finished unit test for synchronization :

  - adding workflows
  - update, delete and add local roles
- updated the code in order to make this tests working fine


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@392 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent d80a5e97
This diff is collapsed.
......@@ -187,9 +187,9 @@ class Signature(SyncCode):
"""
# Constructor
def __init__(self,gid=None, status=None, xml_string=None):
def __init__(self,gid=None, id=None, status=None, xml_string=None):
self.setGid(gid)
self.setId(None)
self.setId(id)
self.status = status
self.setXML(xml_string)
self.partial_xml = None
......@@ -595,14 +595,14 @@ class Subscription(SyncCode, Implicit):
"""
self.xml_mapping = xml_mapping
def setGidGenerator(self, method_id):
def setGidGenerator(self, method):
"""
This set the method name wich allows to find a gid
from any object
"""
if method_id in (None,''):
method_id = 'getId'
self.gid_generator = method_id
if method in (None,''):
method = 'getId'
self.gid_generator = method
def getGidGenerator(self):
"""
......@@ -611,6 +611,22 @@ class Subscription(SyncCode, Implicit):
"""
return self.gid_generator
def getGidFromObject(self, object):
"""
"""
o_base = aq_base(object)
o_gid = None
LOG('getGidFromObject',0,'gidgenerator : %s' % repr(self.getGidGenerator()))
gid_gen = self.getGidGenerator()
if callable(gid_gen):
o_gid=gid_gen(object)
elif hasattr(o_base, gid_gen):
LOG('getGidFromObject',0,'there is the gid generator')
generator = getattr(object, self.getGidGenerator())
o_gid = generator()
LOG('getGidFromObject',0,'o_gid: %s' % repr(o_gid))
return o_gid
def getObjectFromGid(self, gid):
"""
This tries to get the object with the given gid
......@@ -619,15 +635,9 @@ class Subscription(SyncCode, Implicit):
signature = self.getSignature(gid)
# First look if we do already have the mapping between
# the id and the gid
# query_list = []
# query = self.getQuery()
# if query is type('a'):
# query_method = getattr(object,self.getQuery(),None)
# query_list = query()
# if callable(query):
# query_list = query(self)
object_list = self.getObjectList()
destination = self.getDestination()
LOG('getObjectFromGid',0,'gid: %s' % repr(gid))
if signature is not None:
o_id = signature.getId()
o = None
......@@ -639,16 +649,9 @@ class Subscription(SyncCode, Implicit):
return o
for o in object_list:
LOG('getObjectFromGid',0,'working on : %s' % repr(o))
o_base = aq_base(o)
LOG('getObjectFromGid',0,'gidgenerator : %s' % repr(self.getGidGenerator()))
if hasattr(o_base, self.getGidGenerator()):
LOG('getObjectFromGid',0,'there is the gid generator')
generator = getattr(o, self.getGidGenerator())
o_gid = generator()
LOG('getObjectFromGid',0,'o_gid: %s' % repr(o_gid))
LOG('getObjectFromGid',0,'gid: %s' % repr(gid))
if o_gid == gid:
return o
o_gid = self.getGidFromObject(o)
if o_gid == gid:
return o
LOG('getObjectFromGid',0,'returning None')
return None
......@@ -675,20 +678,27 @@ class Subscription(SyncCode, Implicit):
"""
This tries to generate a new Id
"""
if self.getIdGenerator() is not None:
LOG('generateNewId, object: ',0,object.getPhysicalPath())
id_generator = self.getIdGenerator()
LOG('generateNewId, id_generator: ',0,id_generator)
if id_generator is not None:
o_base = aq_base(object)
if hasattr(aq_base, self.getIdGenerator()):
generator = getattr(o, self.getIdGenerator())
new_id = None
if callable(id_generator):
new_id = id_generator(object)
elif hasattr(o_base, id_generator):
generator = getattr(object, id_generator)
new_id = generator()
return new_id
LOG('generateNewId, new_id: ',0,new_id)
return new_id
return None
def setIdGenerator(self, method_id):
def setIdGenerator(self, method):
"""
This set the method name wich allows to generate
a new id
"""
self.id_generator = method_id
self.id_generator = method
def getIdGenerator(self):
"""
......
......@@ -198,14 +198,8 @@ class XMLSyncUtilsMixin(SyncCode):
file2 = open('/tmp/sync_old_object','w')
file2.write(old_xml)
file2.close()
#xupdate = commands.getoutput('xmldiff -xg /tmp/sync_old_object /tmp/sync_new_object')
xupdate = commands.getoutput('erp5diff /tmp/sync_old_object /tmp/sync_new_object')
xupdate = xupdate[xupdate.find('<xupdate:modifications'):]
# XXX To be removed, this is only needed for xmldiff with does bad things
#while xupdate.find('xupdate:move')>0:
# LOG('getXupdateObject',0,'Removing the move section')
# xupdate = xupdate[:xupdate.find('<xupdate:move')] + \
# xupdate[xupdate.find('</xupdate:move>\n')+16:]
return xupdate
def getXMLObject(self, object=None, xml_mapping=None):
......@@ -318,6 +312,17 @@ class XMLSyncUtilsMixin(SyncCode):
return int(subnode.childNodes[0].data)
return None
def getStatusCommand(self, xml):
"""
Return the value of the command inside the xml_stream
"""
# Get informations from the body
if xml.nodeName=='Status':
for subnode in xml.childNodes:
if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == 'Cmd':
return subnode.childNodes[0].data
return None
def getAlertCode(self, xml_stream):
"""
Return the value of the alert code inside the full syncml message
......@@ -428,20 +433,20 @@ class XMLSyncUtilsMixin(SyncCode):
return subnode
return next_status
def getActionObjectId(self, action):
"""
XXX Deprecated
Return the id of the object described by the action
"""
for subnode in action.childNodes:
if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == 'Item':
for subnode2 in subnode.childNodes:
if subnode2.nodeType == subnode2.ELEMENT_NODE and subnode2.nodeName == 'Data':
for subnode3 in subnode2.childNodes:
if subnode3.nodeType == subnode3.ELEMENT_NODE and subnode3.nodeName == 'object':
for subnode4 in subnode3.childNodes:
if subnode4.nodeType == subnode4.ELEMENT_NODE and subnode4.nodeName == 'id':
return str(subnode4.childNodes[0].data)
# def getActionObjectId(self, action):
# """
# XXX Deprecated
# Return the id of the object described by the action
# """
# for subnode in action.childNodes:
# if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == 'Item':
# for subnode2 in subnode.childNodes:
# if subnode2.nodeType == subnode2.ELEMENT_NODE and subnode2.nodeName == 'Data':
# for subnode3 in subnode2.childNodes:
# if subnode3.nodeType == subnode3.ELEMENT_NODE and subnode3.nodeName == 'object':
# for subnode4 in subnode3.childNodes:
# if subnode4.nodeType == subnode4.ELEMENT_NODE and subnode4.nodeName == 'id':
# return str(subnode4.childNodes[0].data)
#return subnode4.childNodes[0].data
def getDataSubNode(self, action):
......@@ -562,20 +567,14 @@ class XMLSyncUtilsMixin(SyncCode):
"""
local_gid_list = []
syncml_data = ''
# store_xupdate = 0
# if object is None:
# object_list = domain.getObjectList()
# else:
# store_xupdate = 1
# object_list = [object]
for object in domain.getObjectList():
status = self.SENT
gid_generator = getattr(object,domain.getGidGenerator(),None)
object_gid = None
if gid_generator is not None:
object_gid = gid_generator()
local_gid_list += [object_gid]
#gid_generator = getattr(object,domain.getGidGenerator(),None)
object_gid = domain.getGidFromObject(object)
local_gid_list += [object_gid]
#if gid_generator is not None:
# object_gid = gid_generator()
force = 0
if syncml_data.count('\n') < self.MAX_LINES and (object.id.find('.')!=0): # If not we have to cut
xml_object = self.getXMLObject(object=object,xml_mapping=domain.xml_mapping)
......@@ -597,7 +596,7 @@ class XMLSyncUtilsMixin(SyncCode):
#LOG('PubSyncModif',0,'Current object.getPath: %s' % object.getPath())
LOG('getSyncMLData',0,'no signature for gid: %s' % object_gid)
xml_string = xml_object
signature = Signature(gid=object_gid)
signature = Signature(gid=object_gid,id=object.getId())
signature.setTempXML(xml_object)
if xml_string.count('\n') > self.MAX_LINES:
more_data=1
......@@ -710,7 +709,6 @@ class XMLSyncUtilsMixin(SyncCode):
# were not able to create
syncml_data += self.deleteXMLObject(xml_object=signature.getXML() or '',
object_gid=object_gid,cmd_id=cmd_id)
subscriber.delSignature(object_gid)
return (syncml_data,xml_confirmation,cmd_id)
......@@ -750,7 +748,6 @@ class XMLSyncUtilsMixin(SyncCode):
data_subnode = self.getDataSubNode(next_action)
if next_action.nodeName == 'Add':
# Then store the xml of this new subobject
#object = domain.getObjectFromGid(object=destination_path,gid=object_gid)
if object is None:
object_id = domain.generateNewId(object=destination_path)
conflict_list += conduit.addNode(xml=data_subnode, object=destination_path,
......@@ -763,7 +760,6 @@ class XMLSyncUtilsMixin(SyncCode):
xml_object = ''
if mapping is not None:
xml_object = mapping()
#xml_object = object.asXML()
signature.setStatus(self.SYNCHRONIZED)
signature.setId(object.getId())
signature.setXML(xml_object)
......@@ -785,7 +781,6 @@ class XMLSyncUtilsMixin(SyncCode):
xml_object = ''
if mapping is not None:
xml_object = mapping()
#xml_object = object.asXML()
signature.setTempXML(xml_object)
if conflict_list != []:
status_code = self.CONFLICT
......@@ -809,16 +804,14 @@ class XMLSyncUtilsMixin(SyncCode):
data_subnode_string = string_io.getvalue()
LOG('applyActionList, subscriber_xupdate:',0,data_subnode_string)
signature.setSubscriberXupdate(data_subnode_string)
# xml_string = self.getXupdateObject(object=object,
# xml_mapping=domain.xml_mapping,
# old_xml=signature.getXML())
# signature.setPublisherXupdate(xml_string) XXX is it needed ??
elif next_action.nodeName == 'Delete':
object_id = object.id
object_id = signature.getId()
conduit.deleteNode(xml=self.getDataSubNode(next_action), object=destination_path,
object_id=self.getActionId(next_action))
object_id=object_id)
subscriber.delSignature(object_gid)
xml_confirmation += self.SyncMLConfirmation(cmd_id,
object_gid,status_code,'Delete')
else: # We want to retrieve more data
signature.setStatus(self.PARTIAL)
#LOG('SyncModif',0,'setPartialXML: %s' % str(previous_partial))
......@@ -851,23 +844,28 @@ class XMLSyncUtilsMixin(SyncCode):
while next_status != None:
object_gid = self.getStatusTarget(next_status)
status_code = self.getStatusCode(next_status)
status_cmd = self.getStatusCommand(next_status)
signature = subscriber.getSignature(object_gid)
LOG('SyncModif',0,'next_status: %s' % str(status_code))
if status_code == self.CHUNK_OK:
destination_waiting_more_data = 1
signature.setStatus(self.PARTIAL)
elif status_code == self.CONFLICT:
signature.setStatus(self.CONFLICT)
elif status_code == self.CONFLICT_MERGE:
# We will have to apply the update, and we should not care about conflicts
# so we have to force the update
signature.setStatus(self.NOT_SYNCHRONIZED)
signature.setForce(1)
elif status_code == self.CONFLICT_CLIENT_WIN:
# The server was agree to apply our updates, nothing to do
signature.setStatus(self.SYNCHRONIZED)
elif status_code == self.SUCCESS:
signature.setStatus(self.SYNCHRONIZED)
if status_cmd in ('Add','Replace'):
if status_code == self.CHUNK_OK:
destination_waiting_more_data = 1
signature.setStatus(self.PARTIAL)
elif status_code == self.CONFLICT:
signature.setStatus(self.CONFLICT)
elif status_code == self.CONFLICT_MERGE:
# We will have to apply the update, and we should not care about conflicts
# so we have to force the update
signature.setStatus(self.NOT_SYNCHRONIZED)
signature.setForce(1)
elif status_code == self.CONFLICT_CLIENT_WIN:
# The server was agree to apply our updates, nothing to do
signature.setStatus(self.SYNCHRONIZED)
elif status_code == self.SUCCESS:
signature.setStatus(self.SYNCHRONIZED)
elif status_cmd == 'Delete':
if status_code == self.SUCCESS:
subscriber.delSignature(object_gid)
next_status = self.getNextSyncBodyStatus(remote_xml, next_status)
return (destination_waiting_more_data, has_status_list)
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment