1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 # Author : Anthony Geay
29 from datetime import datetime
30 import multiprocessing as mp
35 return pickle.dumps(obj,pickle.HIGHEST_PROTOCOL)
37 return pickle.loads(strr)
38 def generateKey(varName,scopeName):
39 dsm=salome.naming_service.Resolve("/DataServerManager")
40 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
42 t=dss.addKeyValueInVarHard(varName,obj2Str("ef"),obj2Str([11,14,100]))
48 generateKey(varName,scopeName)
51 import TestSalomeSDSHelper0
53 fname=os.path.splitext(TestSalomeSDSHelper0.__file__)[0]+".py"
54 proc = subprocess.Popen(["python3", fname], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
55 out,err=proc.communicate()
56 if proc.returncode!=0:
57 print("-------------- work -----------")
60 print("~~~~~~~~~~~~~~ work ~~~~~~~~~~~")
61 return proc.returncode
63 def func_test7(scopeName,cv,cv2,cv3,sharedNum):
66 zeValue={"ab":[4,5,6]}
67 dsm=salome.naming_service.Resolve("/DataServerManager")
68 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName) # should be suspended nbOfSecWait s by main process
70 ######### micro-test1 - check that all requests are suspended
79 t0=dss.createRdWrVarTransac(varName,obj2Str(zeValue))
80 s=(datetime.now()-s).total_seconds()
81 assert(s>=0.99*nbOfSecWait and s<nbOfSecWait*1.01) # expect to wait nearly nbOfSecWait seconds
83 ######### end of micro-test1
84 ######### micro-test2 - after activeRequests everything work well
86 st=dss.fetchSerializedContent(varName)
87 assert(str2Obj(st)==zeValue)
88 s=(datetime.now()-s).total_seconds()
89 assert(s>=0. and s<0.05) # expect to be not locked
90 ######### end of micro-test2
93 dss.takeANap(nbOfSecWait) # emulate a DataServer occupation
96 class SalomeSDSTest(unittest.TestCase):
99 a=SalomeSDSClt.CreateRdExtGlobalVar([],"a","Scope0")
100 self.assertEqual(a.local_copy(),[])
102 self.assertEqual(a.local_copy(),[5])
103 self.assertRaises(SALOME.SALOME_Exception,a.__delitem__,0)
105 self.assertEqual(a.local_copy(),[5,["rt"]])
107 self.assertEqual(a.local_copy(),[5,["rt",8]])
109 self.assertEqual(a.local_copy(),[5,["rt",8],5,["rt",8]])
111 self.assertEqual(a.local_copy(),[5,["rt",8],5,["rt",8],["rt",8]])
113 self.assertEqual(a.local_copy(),[5,["rt",8],5,["rt",8],["rt",8,7]])
114 a.ptr().getMyDataScopeServer().deleteVar("a")
118 a=SalomeSDSClt.CreateRdExtGlobalVar({},"a","Scope0")
120 self.assertEqual(a.local_copy(),{"ab":4})
122 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5]})
124 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77]})
125 a.__setitem__("ef",["a","bb"])
126 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb"]})
127 self.assertRaises(SALOME.SALOME_Exception,a.__setitem__,"ef",["a","bb"])
128 self.assertRaises(SALOME.SALOME_Exception,a.__setitem__,"ef",["a","bb","ccc"])
129 a["ef"].append("ccc")
130 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"]})
132 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"],"gh":{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"]}})
133 a["gh"]["cd"].append(99) ; a["cd"].append(88)
134 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77,88],"ef":["a","bb","ccc"],"gh":{"ab":4,"cd":[5,77,99],"ef":["a","bb","ccc"]}})
135 a.ptr().getMyDataScopeServer().deleteVar("a")
138 def testReadOnly1(self):
139 a=SalomeSDSClt.CreateRdOnlyGlobalVar({"ab":4,"cd":[5,77]},"a","Scope0")
140 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77]})
141 self.assertRaises(Exception,a.__getitem__,"ab")
142 a.ptr().getMyDataScopeServer().deleteVar("a")
144 def testTransaction1(self):
147 dsm=salome.naming_service.Resolve("/DataServerManager")
148 dsm.cleanScopesInNS()
149 if scopeName in dsm.listScopes():
150 dsm.removeDataScope(scopeName)
151 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
152 self.assertTrue(isCreated)
154 t0=dss.createRdWrVarTransac(varName,obj2Str({"ab":[4,5,6]}))
155 dss.atomicApply([t0])
157 self.assertEqual(dss.getAccessOfVar(varName),"RdWr")
159 t1=dss.addKeyValueInVarHard(varName,obj2Str("cd"),obj2Str([7,8,9,10]))
160 dss.atomicApply([t1])
162 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
163 wk=dss.waitForKeyInVar(varName,obj2Str("cd"))
165 self.assertEqual(str2Obj(dss.waitForMonoThrRev(wk)),[7,8,9,10])
168 pool=mp.Pool(processes=nbProc)
169 asyncResult=pool.map_async(work,[(i,varName,scopeName) for i in range(nbProc)])
170 print("asyncResult=", asyncResult)
171 self.assertEqual(asyncResult.get(),nbProc*[0]) # <- the big test is here !
172 dsm.removeDataScope(scopeName)
174 def testTransaction2(self):
177 dsm=salome.naming_service.Resolve("/DataServerManager")
178 dsm.cleanScopesInNS()
179 if scopeName in dsm.listScopes():
180 dsm.removeDataScope(scopeName)
181 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
182 self.assertTrue(isCreated)
184 t0=dss.createRdExtVarTransac(varName,obj2Str({"ab":[4,5,6]}))
185 dss.atomicApply([t0])
187 self.assertEqual(dss.getAccessOfVar(varName),"RdExt")
189 self.assertRaises(SALOME.SALOME_Exception,dss.addKeyValueInVarErrorIfAlreadyExisting,varName,obj2Str("ab"),obj2Str([7,8,9,10]))#raises because ab is already a key !
190 t1=dss.addKeyValueInVarErrorIfAlreadyExisting(varName,obj2Str("cd"),obj2Str([7,8,9,10]))
191 dss.atomicApply([t1])
193 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
194 wk=dss.waitForKeyInVar(varName,obj2Str("cd"))
196 self.assertEqual(str2Obj(dss.waitForMonoThrRev(wk)),[7,8,9,10])
198 def testTransaction3(self):
201 dsm=salome.naming_service.Resolve("/DataServerManager")
202 dsm.cleanScopesInNS()
203 if scopeName in dsm.listScopes():
204 dsm.removeDataScope(scopeName)
205 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
206 self.assertTrue(isCreated)
208 t0=dss.createRdWrVarTransac(varName,obj2Str({"ab":[4,5,6]}))
209 dss.atomicApply([t0])
211 t1=dss.addKeyValueInVarErrorIfAlreadyExisting(varName,obj2Str("cd"),obj2Str([7,8,9,10]))
212 dss.atomicApply([t1])
214 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
216 t2=dss.removeKeyInVarErrorIfNotAlreadyExisting(varName,obj2Str("ab"))
217 dss.atomicApply([t2])
218 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'cd':[7,8,9,10]})
220 def testTransaction4(self):
223 dsm=salome.naming_service.Resolve("/DataServerManager")
224 dsm.cleanScopesInNS()
225 if scopeName in dsm.listScopes():
226 dsm.removeDataScope(scopeName)
227 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
228 self.assertTrue(isCreated)
230 t0=dss.createRdWrVarTransac(varName,obj2Str({"ab":[4,5,6]}))
231 dss.atomicApply([t0])
233 t1=dss.addKeyValueInVarHard(varName,obj2Str("cd"),obj2Str([7,8,9,10]))
234 dss.atomicApply([t1])
236 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
237 wk,t2=dss.waitForKeyInVarAndKillIt(varName,obj2Str("cd"))
238 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
240 self.assertEqual(str2Obj(dss.waitForMonoThrRev(wk)),[7,8,9,10])
241 dss.atomicApply([t2])
242 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6]})
244 def testTransaction5(self):
245 """ Like testTransaction2 but without transactions. """
248 dsm=salome.naming_service.Resolve("/DataServerManager")
249 dsm.cleanScopesInNS()
250 if scopeName in dsm.listScopes():
251 dsm.removeDataScope(scopeName)
252 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
253 self.assertTrue(isCreated)
255 t0=dss.createRdExtVarTransac(varName,obj2Str({"ab":[4,5,6]}))
256 dss.atomicApply([t0])
258 self.assertEqual(dss.getAccessOfVar(varName),"RdExt")
259 t1=dss.addMultiKeyValueSession(varName)
260 self.assertEqual(dss.getAccessOfVar(varName),"RdExtInit")
261 self.assertRaises(SALOME.SALOME_Exception,t1.addKeyValueInVarErrorIfAlreadyExistingNow,obj2Str("ab"),obj2Str([7,8,9,10]))#raises because ab is already a key !
262 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6]})
263 wk=dss.waitForKeyInVar(varName,obj2Str("cd"))
264 t1.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("cd"),obj2Str([7,8,9,10]))
266 self.assertEqual(str2Obj(dss.waitForMonoThrRev(wk)),[7,8,9,10])
267 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6]})# it is not a bug ! commit of t1 not done !
268 dss.atomicApply([t1])
269 self.assertEqual(dss.getAccessOfVar(varName),"RdExt")
271 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
272 wk=dss.waitForKeyInVar(varName,obj2Str("cd"))
274 self.assertEqual(str2Obj(dss.waitForMonoThrRev(wk)),[7,8,9,10])
275 keys=[str2Obj(elt) for elt in dss.getAllKeysOfVarWithTypeDict(varName)]
276 self.assertEqual(set(keys),set(['ab','cd']))
278 def testTransaction6(self):
279 """ Test to test RdWr global vars with transaction"""
282 dsm=salome.naming_service.Resolve("/DataServerManager")
283 dsm.cleanScopesInNS()
284 if scopeName in dsm.listScopes():
285 dsm.removeDataScope(scopeName)
286 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
287 self.assertTrue(isCreated)
289 t0=dss.createWorkingVarTransac(varName,obj2Str({}))
290 a=SalomeSDSClt.GetHandlerFromRef(t0.getVar())
291 self.assertEqual(dss.getAccessOfVar(varName),"RdWr")
294 self.assertEqual(a.local_copy(),{"ab":4})
296 self.assertEqual(a.local_copy(),{"ab":5})
299 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5]})
301 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77]})
302 a.__setitem__("ef",["a","bb"])
303 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb"]})
304 a["ef"].append("ccc")
305 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"]})
307 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"],"gh":{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"]}})
308 a["gh"]["cd"].append(99) ; a["cd"].append(88)
309 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77,88],"ef":["a","bb","ccc"],"gh":{"ab":4,"cd":[5,77,99],"ef":["a","bb","ccc"]}})
310 # WARNING here not problem to overwrite
312 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77,88],"ef":["a","bb","ccc"],"gh":7})
314 self.assertTrue(isinstance(a,SalomeSDSClt.Dict))
315 self.assertTrue(isinstance(a,SalomeSDSClt.WrappedType))# important for EEM
316 # commit : RdWr->RdOnly
317 dss.atomicApply([t0])
319 self.assertEqual(dss.getAccessOfVar(varName),"RdOnly") # after atomicApply the var is readOnly. Impossible to change its value !
320 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{"ab":4,"cd":[5,77,88],"ef":["a","bb","ccc"],"gh":7})
321 dsm.cleanScopesInNS()
322 del a # very important kill Ref before removingDataScope...
323 if scopeName in dsm.listScopes():
324 dsm.removeDataScope(scopeName)
327 def testTransaction7(self):
328 """Like testTransaction5 but after a recovery."""
331 dsm=salome.naming_service.Resolve("/DataServerManager")
332 dsm.cleanScopesInNS()
333 if scopeName in dsm.listScopes():
334 dsm.removeDataScope(scopeName)
335 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
336 self.assertTrue(isCreated)
338 t0=dss.createRdExtInitVarTransac(varName,obj2Str({"ab":[4,5,6]}))
339 dss.atomicApply([t0])
341 self.assertEqual(dss.getAccessOfVar(varName),"RdExtInit")
342 t1=dss.addMultiKeyValueSession(varName)
343 self.assertEqual(dss.getAccessOfVar(varName),"RdExtInit")
344 t1.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("cd"),obj2Str([7,8,9,10]))
345 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6]})# it is not a bug ! commit of t1 not done !
346 dss.atomicApply([t1])
347 self.assertEqual(dss.getAccessOfVar(varName),"RdExt")
348 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
351 def testTransaction8(self):
352 """ EDF 16833 and EDF17719 """
353 funcContent="""def comptchev(a,b):
357 dsm=salome.naming_service.Resolve("/DataServerManager")
358 dsm.cleanScopesInNS()
359 if scopeName in dsm.listScopes():
360 dsm.removeDataScope(scopeName)
361 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
362 self.assertTrue(isCreated)
365 value2={'a':1,'c':3,'b':2}
366 value3={'a':1,'c':3,'b':2,'d':4}
369 t0=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent) # sha1 is the key used to compare the initial value
370 dss.atomicApply([t0])
371 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value)
372 t1=dss.addMultiKeyValueSession(varName)
373 t1.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("c"),obj2Str(3))
374 dss.atomicApply([t1])
375 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value2)
376 t2=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent) # func says OK this is the same (even if it is not the case) as original one -> OK
377 dss.atomicApply([t2])
378 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value2) # value2 remains untouched
379 t3=dss.addMultiKeyValueSession(varName)
380 t3.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("d"),obj2Str(4))
381 dss.atomicApply([t3])
382 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value3)
383 t4=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent)
384 self.assertRaises(SALOME.SALOME_Exception,dss.atomicApply,[t4]) # d is in dict pointed by var. Func returns false -> rejected
385 self.assertRaises(SALOME.SALOME_Exception,dss.fetchSerializedContent,varName) # creation in the previous line fails -> the var has been removed
388 def testTransaction9(self):
389 """ EDF 16833 and EDF17719 : use case 2. Trying to createRdExt during add key session"""
390 funcContent="""def comptchev(a,b):
394 dsm=salome.naming_service.Resolve("/DataServerManager")
395 dsm.cleanScopesInNS()
396 if scopeName in dsm.listScopes():
397 dsm.removeDataScope(scopeName)
398 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
399 self.assertTrue(isCreated)
402 value2={'a':1,'c':3,'b':2}
405 t0=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent)
406 dss.atomicApply([t0])
407 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value)
408 t1=dss.addMultiKeyValueSession(varName)
409 t2=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent)
410 dss.atomicApply([t2])
411 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value)
412 t1.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("c"),obj2Str(3))
413 dss.atomicApply([t1])
414 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value2)
418 def testLockToDump(self):
419 """ Test to check that holdRequests method. This method wait for clean server status and hold it until activeRequests is called.
420 Warning this method expects a not overloaded machine to be run because test is based on ellapse time.
425 dsm=salome.naming_service.Resolve("/DataServerManager")
426 dsm.cleanScopesInNS()
427 if scopeName in dsm.listScopes():
428 dsm.removeDataScope(scopeName)
429 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
430 self.assertTrue(isCreated)
431 cv=mp.Condition(mp.Lock())
432 cv2=mp.Condition(mp.Lock()) # sharedNum & cv2 & cv3 for the barrier
433 cv3=mp.Condition(mp.Lock())
434 sharedNum=mp.Value('b',False)
435 p=mp.Process(target=func_test7,args=(scopeName,cv,cv2,cv3,sharedNum))
438 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
439 self.assertTrue(not isCreated)
440 t0=dss.createRdWrVarTransac(varName,obj2Str(zeObj))
441 dss.atomicApply([t0])
442 rs=dss.getRequestSwitcher()
443 self.assertTrue(not isCreated)
446 if not sharedNum.value:
448 sharedNum.value=False
453 rs.holdRequests() # The aim of the test
454 self.assertEqual(rs.listVars(),[varName]) # call whereas holdRequest is called
455 time.sleep(nbOfSecWait)
456 rs.activeRequests() # The aim of the test
457 ######### micro-test3 - check that holdRequests is able to wait for a non finished job
461 time.sleep(0.01) # let main proc the priority
462 rs.holdRequests() # the aim of the test is here. main process is occupied 1s -> holdRequests is Expected to wait
463 s=(datetime.now()-s).total_seconds()
464 self.assertTrue(str2Obj(rs.fetchSerializedContent(varName))==zeObj) # call whereas holdRequest is called
466 self.assertTrue(s>=0.99*nbOfSecWait and s<nbOfSecWait*1.01) # expect to be not locked
477 if __name__=="__main__":