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