Commit 01840c37 authored by Sebastien Robin's avatar Sebastien Robin

added new tests (change an object on two different places at the same time,

                 working on subojbects)
added the simulation of conflicts in the synchronization
corrected some bugs


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@387 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 02f2305d
......@@ -103,7 +103,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
security.declareProtected(Permissions.ModifyPortalContent, 'addNode')
def addNode(self, xml=None, object=None, previous_xml=None,
object_id=None, force=0, **kw):
object_id=None, force=0, simulate=0, **kw):
"""
A node is added
......@@ -132,7 +132,8 @@ class ERP5Conduit(XMLSyncUtilsMixin):
for element in self.getXupdateElementList(xml):
xml = self.getElementFromXupdate(element)
conflict_list += self.addNode(xml=xml,object=object,
previous_xml=previous_xml, force=force, **kw)
previous_xml=previous_xml, force=force,
simulate=simulate, **kw)
elif xml.nodeName == 'object':
if object_id is None:
object_id = self.getAttribute(xml,'id')
......@@ -170,7 +171,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
px_tool._modifyProxy(proxy,rpath)
subobject = object._getOb(object_id)
self.newObject(object=subobject,xml=xml)
self.newObject(object=subobject,xml=xml,simulate=simulate)
elif xml.nodeName in self.XUPDATE_INSERT_OR_ADD \
and self.getSubObjectDepth(xml)>=1:
sub_object_id = self.getSubObjectId(xml)
......@@ -194,7 +195,8 @@ class ERP5Conduit(XMLSyncUtilsMixin):
LOG('addNode',0,'sub_xml: %s' % str(sub_xml))
# Then do the udpate
conflict_list += self.addNode(xml=sub_xml,object=sub_object,
previous_xml=sub_previous_xml, force=force)
previous_xml=sub_previous_xml, force=force,
simulate=simulate, **kw)
elif xml.nodeName == self.history_tag or self.isHistoryAdd(xml)>0:
# We want to add a workflow action
wf_tool = getToolByName(object,'portal_workflow')
......@@ -211,12 +213,12 @@ class ERP5Conduit(XMLSyncUtilsMixin):
status=status,wf_tool=wf_tool,
xml=xml)
LOG('addNode, workflow_history wf_conflict_list:',0,wf_conflict_list)
if wf_conflict_list==[] or force:
if wf_conflict_list==[] or force and not simulate:
LOG('addNode, setting status:',0,'ok')
wf_tool.setStatusOf(wf_id,object,status)
else:
conflict_list += wf_conflict_list
elif xml.nodeName in self.local_role_list:
elif xml.nodeName in self.local_role_list and not simulate:
# We want to add a local role
roles = self.convertXmlValue(xml.childNodes[0].data,data_type='tokens')
roles = list(roles) # Needed for CPS, or we have a CPS error
......@@ -224,11 +226,13 @@ class ERP5Conduit(XMLSyncUtilsMixin):
roles = roles[1:]
object.manage_setLocalRoles(user,roles)
else:
conflict_list += self.updateNode(xml=xml,object=object, force=force, **kw)
conflict_list += self.updateNode(xml=xml,object=object, force=force,
simulate=simulate, **kw)
return conflict_list
security.declareProtected(Permissions.ModifyPortalContent, 'deleteNode')
def deleteNode(self, xml=None, object=None, object_id=None, force=None, **kw):
def deleteNode(self, xml=None, object=None, object_id=None, force=None,
simulate=0, **kw):
"""
A node is deleted
"""
......@@ -251,7 +255,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
sub_object = object._getOb(sub_object_id)
sub_xml = self.getSubObjectXupdate(xml)
conflict_list += self.deleteNode(xml=sub_xml,object=sub_object,
force=force)
force=force, simulate=simulate, **kw)
except KeyError:
pass
else: # We do have an object_id
......@@ -263,7 +267,8 @@ class ERP5Conduit(XMLSyncUtilsMixin):
return conflict_list
security.declareProtected(Permissions.ModifyPortalContent, 'updateNode')
def updateNode(self, xml=None, object=None, previous_xml=None, force=0, **kw):
def updateNode(self, xml=None, object=None, previous_xml=None, force=0,
simulate=0, **kw):
"""
A node is updated with some xupdate
- xml : the xml corresponding to the update, it should be xupdate
......@@ -280,7 +285,8 @@ class ERP5Conduit(XMLSyncUtilsMixin):
#xupdate_utils = XupdateUtils()
xupdate_utils = self
conflict_list += xupdate_utils.applyXupdate(object=object,xupdate=xml,conduit=self,
previous_xml=previous_xml, force=force)
previous_xml=previous_xml, force=force, simulate=simulate,
**kw)
# we may have only the part of an xupdate
else:
args = {}
......@@ -358,7 +364,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
#publisher_value=current_data, # not needed any more
#subscriber_value=data)] # not needed any more
# We will now apply the argument with the method edit
if args != {} and (isConflict==0 or force):
if args != {} and (isConflict==0 or force) and (not simulate):
LOG('updateNode',0,'object._edit, args: %s' % str(args))
object._edit(**args)
# It is sometimes required to do something after an edit
......@@ -368,12 +374,14 @@ class ERP5Conduit(XMLSyncUtilsMixin):
if keyword == 'object':
# This is the case where we have to call addNode
LOG('updateNode',0,'we will add sub-object')
conflict_list += self.addNode(xml=subnode,object=object,force=force)
elif keyword == self.history_tag:
conflict_list += self.addNode(xml=subnode,object=object,force=force,
simulate=simulate, **kw)
elif keyword == self.history_tag and not simulate:
# This is the case where we have to call addNode
LOG('updateNode',0,'we will add history')
conflict_list += self.addNode(xml=subnode,object=object,force=force)
elif keyword == self.local_role_tag:
conflict_list += self.addNode(xml=subnode,object=object,force=force,
simulate=simulate,**kw)
elif keyword == self.local_role_tag and not simulate:
# This is the case where we have to call addNode
LOG('updateNode',0,'we will add a local role')
roles = self.convertXmlValue(data,data_type='tokens')
......@@ -403,7 +411,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
LOG('updateNode',0,'sub_xml: %s' % str(sub_xml))
# Then do the udpate
conflict_list += self.updateNode(xml=sub_xml,object=sub_object, force=force,
previous_xml=sub_previous_xml)
previous_xml=sub_previous_xml,simulate=simulate, **kw)
return conflict_list
security.declareProtected(Permissions.AccessContentsInformation,'getFormatedArgs')
......@@ -635,7 +643,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
except IndexError: # There is no data
data = None
data = self.convertXmlValue(data, data_type=data_type)
LOG('getObjectProperty',0,'prop; %s, data_type:%s, data: %s' % (property,data_type,data))
return data
return None
......@@ -699,12 +706,14 @@ class ERP5Conduit(XMLSyncUtilsMixin):
security.declareProtected(Permissions.ModifyPortalContent, 'newObject')
def newObject(self, object=None, xml=None):
def newObject(self, object=None, xml=None, simulate=0):
"""
modify the object with datas from
the xml (action section)
"""
args = {}
if simulate:
return
# Retrieve the list of users with a role and delete default roles
user_role_list = map(lambda x:x[0],object.get_local_roles())
object.manage_delLocalRoles(user_role_list)
......@@ -766,7 +775,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
for subnode in self.getElementNodeList(xml):
if subnode.nodeName in self.XUPDATE_EL:
e_list += [subnode]
LOG('getXupdateElementList, e_list:%',0,e_list)
LOG('getXupdateElementList, e_list:',0,e_list)
return e_list
security.declareProtected(Permissions.AccessContentsInformation,'getElementFromXupdate')
......@@ -775,7 +784,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
from a xupdate:element returns the element as xml
"""
if xml.nodeName in self.XUPDATE_EL:
result = '<'
result = u'<'
result += xml.attributes[0].nodeValue
for subnode in self.getElementNodeList(xml): #getElementNodeList
if subnode.nodeName == 'xupdate:attribute':
......@@ -786,11 +795,11 @@ class ERP5Conduit(XMLSyncUtilsMixin):
xml_string = StringIO()
PrettyPrint(xml,xml_string)
xml_string = xml_string.getvalue()
xml_string = unicode(xml_string,encoding='utf-8')
maxi = max(xml_string.find('>')+1,\
xml_string.rfind('</xupdate:attribute>')+len('</xupdate:attribute>'))
result += xml_string[maxi:xml_string.find('</xupdate:element>')]
result += '</' + xml.attributes[0].nodeValue + '>'
LOG('getElementFromXupdate, result:',0,result)
return self.convertToXml(result)
return xml
......@@ -856,7 +865,8 @@ class ERP5Conduit(XMLSyncUtilsMixin):
# XXX is it the right place ? It should be in XupdateUtils, but here we
# have some specific things to do
security.declareProtected(Permissions.ModifyPortalContent, 'applyXupdate')
def applyXupdate(self, object=None, xupdate=None, conduit=None, force=0, **kw):
def applyXupdate(self, object=None, xupdate=None, conduit=None, force=0,
simulate=0, **kw):
"""
Parse the xupdate and then it will call the conduit
"""
......@@ -869,13 +879,13 @@ class ERP5Conduit(XMLSyncUtilsMixin):
selection_name = ''
if subnode.nodeName in self.XUPDATE_INSERT_OR_ADD:
conflict_list += conduit.addNode(xml=sub_xupdate,object=object, \
force=force, **kw)
force=force, simulate=simulate, **kw)
elif subnode.nodeName in self.XUPDATE_DEL:
conflict_list += conduit.deleteNode(xml=sub_xupdate, object=object, \
force=force, **kw)
force=force, simulate=simulate, **kw)
elif subnode.nodeName in self.XUPDATE_UPDATE:
conflict_list += conduit.updateNode(xml=sub_xupdate, object=object, \
force=force, **kw)
force=force, simulate=simulate, **kw)
#elif subnode.nodeName in self.XUPDATE_INSERT:
# conflict_list += conduit.addNode(xml=subnode, object=object, force=force, **kw)
......
......@@ -198,6 +198,8 @@ class Signature(SyncCode):
self.resetConflictList()
self.md5_string = None
self.force = 0
self.setSubscriberXupdate(None)
self.setPublisherXupdate(None)
#def __init__(self,object=None, status=None, xml_string=None):
# self.uid = object.uid
......@@ -271,6 +273,30 @@ class Signature(SyncCode):
"""
return self.temp_xml
def setSubscriberXupdate(self, xupdate):
"""
set the full temp xupdate
"""
self.subscriber_xupdate = xupdate
def getSubscriberXupdate(self):
"""
get the full temp xupdate
"""
return self.subscriber_xupdate
def setPublisherXupdate(self, xupdate):
"""
set the full temp xupdate
"""
self.publisher_xupdate = xupdate
def getPublisherXupdate(self):
"""
get the full temp xupdate
"""
return self.publisher_xupdate
def setMD5(self, xml):
"""
set the MD5 object of this signature
......
......@@ -552,13 +552,23 @@ class XMLSyncUtilsMixin(SyncCode):
def getSyncMLData(self, domain=None,remote_xml=None,cmd_id=0,
subscriber=None,destination_path=None,
xml_confirmation=None):
xml_confirmation=None,conduit=None):
"""
This generate the syncml data message. This returns a string
with all modification made locally (ie replace, add ,delete...)
if object is not None, this usually means we want to set the
actual xupdate on the signature.
"""
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)
......@@ -575,6 +585,7 @@ class XMLSyncUtilsMixin(SyncCode):
LOG('getSyncMLData',0,'hasSignature: %s' % str(subscriber.hasSignature(object_gid)))
LOG('getSyncMLData',0,'alert_code == slowsync: %s' % str(self.getAlertCode(remote_xml)==self.SLOW_SYNC))
signature = subscriber.getSignature(object_gid)
LOG('getSyncMLData',0,'current object: %s' % str(object.getId()))
if signature is not None:
LOG('getSyncMLData',0,'signature.status: %s' % str(signature.getStatus()))
LOG('getSyncMLData',0,'signature.action: %s' % str(signature.getAction()))
......@@ -615,7 +626,9 @@ class XMLSyncUtilsMixin(SyncCode):
if signature.getStatus()==self.PUB_CONFLICT_MERGE:
xml_confirmation += self.SyncMLConfirmation(cmd_id,object.id,
self.CONFLICT_MERGE,'Replace')
set_synchronized = 1
if not signature.checkMD5(xml_object):
set_synchronized = 0
# This object has changed on this side, we have to generate some xmldiff
xml_string = self.getXupdateObject(object=object,
xml_mapping=domain.xml_mapping,
......@@ -638,7 +651,18 @@ class XMLSyncUtilsMixin(SyncCode):
xml_string=xml_string, more_data=more_data)
cmd_id += 1
signature.setTempXML(xml_object)
else: # We should not have this case when we are in CONFLICT_MERGE
# Now we can apply the xupdate from the subscriber
subscriber_xupdate = signature.getSubscriberXupdate()
LOG('getSyncMLData subscriber_xupdate',0,subscriber_xupdate)
if subscriber_xupdate is not None:
old_xml = signature.getXML()
conduit.updateNode(xml=subscriber_xupdate, object=object,
previous_xml=old_xml,force=(domain.getDomainType==self.SUB),
simulate=0)
xml_object = self.getXMLObject(object=object,xml_mapping=domain.xml_mapping)
signature.setTempXML(xml_object)
if set_synchronized: # We have to do that after this previous update
# We should not have this case when we are in CONFLICT_MERGE
signature.setStatus(self.SYNCHRONIZED)
elif signature.getStatus()==self.PUB_CONFLICT_CLIENT_WIN:
# We have decided to apply the update
......@@ -691,7 +715,7 @@ class XMLSyncUtilsMixin(SyncCode):
return (syncml_data,xml_confirmation,cmd_id)
def applyActionList(self, domain=None, subscriber=None,destination_path=None,
cmd_id=0,remote_xml=None,conduit=None):
cmd_id=0,remote_xml=None,conduit=None,simulate=0):
"""
This just look to a list of action to do, then id applies
each action one by one, thanks to a conduit
......@@ -706,8 +730,6 @@ class XMLSyncUtilsMixin(SyncCode):
status_code = self.SUCCESS
# Thirst we have to check the kind of action it is
partial_data = self.getPartialData(next_action)
#LOG('XMLSyncUtils',0,'partial_data: %s' % str(partial_data))
#LOG('XMLSyncUtils',0,'checkActionMoreData: %s' % str(self.checkActionMoreData(next_action)))
object_gid = self.getActionId(next_action)
signature = subscriber.getSignature(object_gid)
if signature == None:
......@@ -749,12 +771,6 @@ class XMLSyncUtilsMixin(SyncCode):
self.SyncMLConfirmation(cmd_id,object_gid,self.SUCCESS,'Add')
cmd_id +=1
elif next_action.nodeName == 'Replace':
#object = domain.getObjectFromGid(object=destination_path,gid=object_gid)
# object =None
# try:
# object = destination_path._getOb(self.getActionId(next_action))
# except (AttributeError, KeyError):
# pass
LOG('SyncModif',0,'object: %s will be updated...' % str(object))
if object is not None:
LOG('SyncModif',0,'object: %s will be updated...' % object.id)
......@@ -763,7 +779,8 @@ class XMLSyncUtilsMixin(SyncCode):
previous_xml = signature.getXML()
LOG('SyncModif',0,'previous signature: %i' % len(previous_xml))
conflict_list += conduit.updateNode(xml=data_subnode, object=object,
previous_xml=signature.getXML(),force=force)
previous_xml=signature.getXML(),force=force,
simulate=simulate)
mapping = getattr(object,domain.getXMLMapping(),None)
xml_object = ''
if mapping is not None:
......@@ -778,11 +795,25 @@ class XMLSyncUtilsMixin(SyncCode):
PrettyPrint(data_subnode,stream=string_io)
data_subnode_string = string_io.getvalue()
signature.setPartialXML(data_subnode_string)
else:
elif not simulate:
signature.setStatus(self.SYNCHRONIZED)
xml_confirmation += self.SyncMLConfirmation(cmd_id,
object_gid,status_code,'Replace')
cmd_id +=1
if simulate:
# This means we are on the publiher side and we want to store
# the xupdate from the subscriber and we also want to generate
# the current xupdate from the last synchronization
string_io = StringIO()
PrettyPrint(data_subnode,stream=string_io)
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
conduit.deleteNode(xml=self.getDataSubNode(next_action), object=destination_path,
......@@ -881,7 +912,9 @@ class XMLSyncUtils(XMLSyncUtilsMixin):
return
subscriber = domain # If we are the client, this is fine
simulate = 0 # used by applyActionList, should be 0 for client
if domain.domain_type == self.PUB:
simulate = 1
for subnode in xml_header.childNodes:
if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == "Source":
subscription_url = str(subnode.childNodes[0].data)
......@@ -901,7 +934,7 @@ class XMLSyncUtils(XMLSyncUtilsMixin):
destination_path=destination_path,
subscriber=subscriber,
remote_xml=remote_xml,
conduit=conduit)
conduit=conduit, simulate=simulate)
LOG('SyncModif, has_next_action:',0,has_next_action)
xml = ""
......@@ -925,7 +958,8 @@ class XMLSyncUtils(XMLSyncUtilsMixin):
remote_xml=remote_xml,
subscriber=subscriber,
destination_path=destination_path,
cmd_id=cmd_id,xml_confirmation=xml_confirmation)
cmd_id=cmd_id,xml_confirmation=xml_confirmation,
conduit=conduit)
# syncml body
xml += ' <SyncBody>\n'
......
......@@ -58,10 +58,10 @@ class TestERP5SyncML(ERP5TypeTestCase):
description1 = 'description1 $sdfr_sdfsdf_oisfsopf'
first_name2 = 'Jean-Paul'
last_name2 = 'Smets'
description2 = 'descrip ti on2@ $*<<<<>>>></title>&oekd'
description2 = 'description2@ $*< <<< >>>></title>&oekd'
first_name3 = 'Yoshinori'
last_name3 = 'Okuji'
description3 = 'description sdf__sdf_df___&&]]]'
description3 = 'description3 sdf__sdf_df___&&]]]'
xml_mapping = 'asXML'
id1 = '170'
id2 = '171'
......@@ -157,11 +157,11 @@ class TestERP5SyncML(ERP5TypeTestCase):
user = uf.getUserById('ERP5TypeTestCase').__of__(uf)
newSecurityManager(None, user)
def testPopulatePersonServer(self, quiet=0, run=run_all_test):
def populatePersonServer(self, quiet=0, run=run_all_test):
if not run: return
if not quiet:
ZopeTestCase._print('\nTest Populate Person Server ')
LOG('Testing... ',0,'testPopulatePersonServer')
LOG('Testing... ',0,'populatePersonServer')
self.login()
person_server = self.getPersonServer()
person_id = ''
......@@ -205,7 +205,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
LOG('Testing... ',0,'testGetObjectList')
self.login()
self.setupPublicationAndSubscription(quiet=1,run=1)
nb_person = self.testPopulatePersonServer(quiet=1,run=1)
nb_person = self.populatePersonServer(quiet=1,run=1)
portal_sync = self.getSynchronizationTool()
publication_list = portal_sync.getPublicationList()
publication = publication_list[0]
......@@ -231,7 +231,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
ZopeTestCase._print('\nTest Export and Import ')
LOG('Testing... ',0,'testExportImport')
self.login()
self.testPopulatePersonServer(quiet=1,run=1)
self.populatePersonServer(quiet=1,run=1)
person_server = self.getPersonServer()
person_client1 = self.getPersonClient1()
person = person_server._getOb(self.id1)
......@@ -278,7 +278,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
LOG('Testing... ',0,'testFirstSynchronization')
self.login()
self.setupPublicationAndSubscription(quiet=1,run=1)
nb_person = self.testPopulatePersonServer(quiet=1,run=1)
nb_person = self.populatePersonServer(quiet=1,run=1)
# Synchronize the first client
nb_message1 = self.synchronize(self.sub_id1)
self.failUnless(nb_message1==self.nb_message_first_synchronization)
......@@ -316,7 +316,7 @@ class TestERP5SyncML(ERP5TypeTestCase):
LOG('Testing... ',0,'testGetObjectFromGid')
self.login()
self.setupPublicationAndSubscription(quiet=1,run=1)
self.testPopulatePersonServer(quiet=1,run=1)
self.populatePersonServer(quiet=1,run=1)
# By default we can just give the id
portal_sync = self.getSynchronizationTool()
publication = portal_sync.getPublication(self.pub_id)
......@@ -400,13 +400,12 @@ class TestERP5SyncML(ERP5TypeTestCase):
person1_s.edit(**kw)
kw = {'description':self.description3}
person1_c.edit(**kw)
# XXX Warning XXX This does not works actually, need to be CORRECTED !!!!
# self.synchronize(self.sub_id1)
# self.checkSynchronizationStateIsSynchronized()
# self.failUnless(person1_s.getFirstName()==self.first_name3)
# self.failUnless(person1_s.getDescription()==self.description3)
# self.failUnless(person1_c.getFirstName()==self.first_name3)
# self.failUnless(person1_c.getDescription()==self.description3)
self.synchronize(self.sub_id1)
self.checkSynchronizationStateIsSynchronized()
self.failUnless(person1_s.getFirstName()==self.first_name3)
self.failUnless(person1_s.getDescription()==self.description3)
self.failUnless(person1_c.getFirstName()==self.first_name3)
self.failUnless(person1_c.getDescription()==self.description3)
def testGetConflictList(self, quiet=0, run=run_all_test):
# We will try to generate a conflict and then to get it
......@@ -428,6 +427,8 @@ class TestERP5SyncML(ERP5TypeTestCase):
conflict_list = portal_sync.getConflictList()
self.failUnless(len(conflict_list)==1)
conflict = conflict_list[0]
self.failUnless(person1_c.getDescription()==self.description3)
self.failUnless(person1_s.getDescription()==self.description2)
self.failUnless(conflict.getPropertyId()=='description')
self.failUnless(conflict.getPublisherValue()==self.description2)
self.failUnless(conflict.getSubscriberValue()==self.description3)
......@@ -438,10 +439,10 @@ class TestERP5SyncML(ERP5TypeTestCase):
# We will try to generate a conflict and then to get it
# We will also make sure it contains what we want
if not run: return
self.testGetConflictList(quiet=1,run=1)
if not quiet:
ZopeTestCase._print('\nTest Apply Publisher Value ')
LOG('Testing... ',0,'testApplyPublisherValue')
self.testGetConflictList(quiet=1,run=1)
portal_sync = self.getSynchronizationTool()
conflict_list = portal_sync.getConflictList()
conflict = conflict_list[0]
......@@ -452,8 +453,8 @@ class TestERP5SyncML(ERP5TypeTestCase):
conflict.applyPublisherValue()
self.synchronize(self.sub_id1)
self.checkSynchronizationStateIsSynchronized()
self.failUnless(person1_s.getDescription()==self.description2)
self.failUnless(person1_c.getDescription()==self.description2)
self.failUnless(person1_s.getDescription()==self.description2)
conflict_list = portal_sync.getConflictList()
self.failUnless(len(conflict_list)==0)
......@@ -461,12 +462,12 @@ class TestERP5SyncML(ERP5TypeTestCase):
# We will try to generate a conflict and then to get it
# We will also make sure it contains what we want
if not run: return
if not quiet:
ZopeTestCase._print('\nTest Apply Subscriber Value ')
LOG('Testing... ',0,'testApplySubscriberValue')
self.testGetConflictList(quiet=1,run=1)
portal_sync = self.getSynchronizationTool()
conflict_list = portal_sync.getConflictList()
if not quiet:
ZopeTestCase._print('\nTest Apply Subscriber Value ')
LOG('Testing... ',0,'testApplySubscriberValue')
conflict = conflict_list[0]
person_server = self.getPersonServer()
person1_s = person_server._getOb(self.id1)
......@@ -480,30 +481,86 @@ class TestERP5SyncML(ERP5TypeTestCase):
conflict_list = portal_sync.getConflictList()
self.failUnless(len(conflict_list)==0)
# def testPopulatePersonServerWithSubObject(self, quiet=0, run=1):
# if not run: return
# if not quiet:
# ZopeTestCase._print('\nTest Populate Person Server With Sub Object ')
# LOG('Testing... ',0,'testPopulatePersonServerWithSubObject')
# self.testPopulatePersonServer(quiet=1,run=1)
# person_server = self.getPersonServer()
# person1 = person_server._getOb(self.id1)
# sub_person1 = person1.newContent(id=self.id1,portal_type='Person')
# person2 = person_server.newContent(id=self.id2,portal_type='Person')
# kw = {'first_name':self.first_name1,'last_name':self.last_name1,
# 'description':self.description1}
# person1.edit(**kw)
# kw = {'first_name':self.first_name2,'last_name':self.last_name2,
# 'description':self.description2}
# person2.edit(**kw)
# nb_person = len(person_server.objectValues())
# self.failUnless(nb_person==2)
# return nb_person
# XXX TODO : need to add a test with all kind of strange sign, like &, ...><
def populatePersonServerWithSubObject(self, quiet=0, run=run_all_test):
"""
Before this method, we need to call populatePersonServer
Then it will give the following tree :
- person_server :
- id1
- id1
- id2
- id2
"""
if not run: return
if not quiet:
ZopeTestCase._print('\nTest Populate Person Server With Sub Object ')
LOG('Testing... ',0,'populatePersonServerWithSubObject')
person_server = self.getPersonServer()
person1 = person_server._getOb(self.id1)
sub_person1 = person1.newContent(id=self.id1,portal_type='Person')
kw = {'first_name':self.first_name1,'last_name':self.last_name1,
'description':self.description1}
sub_person1.edit(**kw)
sub_sub_person = sub_person1.newContent(id=self.id2,portal_type='Person')
kw = {'first_name':self.first_name2,'last_name':self.last_name2,
'description':self.description2}
sub_sub_person.edit(**kw)
# remove ('','portal...','person_server')
len_path = len(sub_sub_person.getPhysicalPath()) - 3
self.failUnless(len_path==3)
def testAddSubObject(self, quiet=0, run=run_all_test):
"""
In this test, we synchronize, then add sub object on the
server and then see if the next synchronization will also
create sub-objects on the client
"""
if not run: return
self.testFirstSynchronization(quiet=1,run=1)
if not quiet:
ZopeTestCase._print('\nTest Add Sub Object ')
LOG('Testing... ',0,'testAddSubObject')
self.populatePersonServerWithSubObject(quiet=1,run=1)
self.synchronize(self.sub_id1)
self.checkSynchronizationStateIsSynchronized()
person_client1 = self.getPersonClient1()
person1_c = person_client1._getOb(self.id1)
sub_person1_c = person1_c._getOb(self.id1)
sub_sub_person = sub_person1_c._getOb(self.id2)
# remove ('','portal...','person_server')
len_path = len(sub_sub_person.getPhysicalPath()) - 3
self.failUnless(len_path==3)
self.failUnless(sub_sub_person.getDescription()==self.description2)
self.failUnless(sub_sub_person.getFirstName()==self.first_name2)
self.failUnless(sub_sub_person.getLastName()==self.last_name2)
def testUpdateSubObject(self, quiet=0, run=1):
"""
In this test, we start with a tree of object already
synchronized, then we update a subobject, and we will see
if it is updated correctly
"""
if not run: return
self.testAddSubObject(quiet=1,run=1)
if not quiet:
ZopeTestCase._print('\nTest Update Sub Object ')
LOG('Testing... ',0,'testUpdateSubObject')
person_client1 = self.getPersonClient1()
person1_c = person_client1._getOb(self.id1)
sub_person1_c = person1_c._getOb(self.id1)
sub_sub_person_c = sub_person1_c._getOb(self.id2)
person_server = self.getPersonServer()
sub_sub_person_s = person_server._getOb(self.id1)._getOb(self.id1)._getOb(self.id2)
kw = {'first_name':self.first_name3}
sub_sub_person_c.edit(**kw)
kw = {'description':self.description3}
sub_sub_person_s.edit(**kw)
self.synchronize(self.sub_id1)
self.checkSynchronizationStateIsSynchronized()
self.failUnless(sub_sub_person_c.getDescription()==self.description3)
self.failUnless(sub_sub_person_c.getFirstName()==self.first_name3)
self.failUnless(sub_sub_person_s.getDescription()==self.description3)
self.failUnless(sub_sub_person_s.getFirstName()==self.first_name3)
if __name__ == '__main__':
framework()
......
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