1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2024 CEA, EDF, 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]))
46 IORNS,i,varName,scopeName=t
48 generateKey(varName,scopeName)
51 import TestSalomeSDSHelper0
53 fname=os.path.splitext(TestSalomeSDSHelper0.__file__)[0]+".py"
54 proc = subprocess.Popen(["python3", fname, IORNS], 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))
81 s=(datetime.now()-s).total_seconds()
82 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):
100 a=SalomeSDSClt.CreateRdExtGlobalVar([],"a",scopeName)
101 self.assertEqual(a.local_copy(),[])
103 self.assertEqual(a.local_copy(),[5])
104 self.assertRaises(SALOME.SALOME_Exception,a.__delitem__,0)
106 self.assertEqual(a.local_copy(),[5,["rt"]])
108 self.assertEqual(a.local_copy(),[5,["rt",8]])
110 self.assertEqual(a.local_copy(),[5,["rt",8],5,["rt",8]])
112 self.assertEqual(a.local_copy(),[5,["rt",8],5,["rt",8],["rt",8]])
114 self.assertEqual(a.local_copy(),[5,["rt",8],5,["rt",8],["rt",8,7]])
115 a.ptr().getMyDataScopeServer().deleteVar("a")
119 salome.dsm.removeDataScope(scopeName)
124 a=SalomeSDSClt.CreateRdExtGlobalVar({},"a",scopeName)
126 self.assertEqual(a.local_copy(),{"ab":4})
128 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5]})
130 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77]})
131 a.__setitem__("ef",["a","bb"])
132 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb"]})
133 self.assertRaises(SALOME.SALOME_Exception,a.__setitem__,"ef",["a","bb"])
134 self.assertRaises(SALOME.SALOME_Exception,a.__setitem__,"ef",["a","bb","ccc"])
135 a["ef"].append("ccc")
136 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"]})
138 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"],"gh":{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"]}})
139 a["gh"]["cd"].append(99) ; a["cd"].append(88)
140 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"]}})
141 a.ptr().getMyDataScopeServer().deleteVar("a")
145 salome.dsm.removeDataScope(scopeName)
148 def testReadOnly1(self):
151 a=SalomeSDSClt.CreateRdOnlyGlobalVar({"ab":4,"cd":[5,77]},"a",scopeName)
152 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77]})
153 self.assertRaises(Exception,a.__getitem__,"ab")
154 a.ptr().getMyDataScopeServer().deleteVar("a")
159 salome.dsm.removeDataScope(scopeName)
161 def testTransaction1(self):
164 dsm=salome.naming_service.Resolve("/DataServerManager")
165 dsm.cleanScopesInNS()
166 if scopeName in dsm.listScopes():
167 dsm.removeDataScope(scopeName)
168 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
169 self.assertTrue(isCreated)
171 t0=dss.createRdWrVarTransac(varName,obj2Str({"ab":[4,5,6]}))
172 dss.atomicApply([t0])
174 self.assertEqual(dss.getAccessOfVar(varName),"RdWr")
176 t1=dss.addKeyValueInVarHard(varName,obj2Str("cd"),obj2Str([7,8,9,10]))
177 dss.atomicApply([t1])
179 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
180 wk=dss.waitForKeyInVar(varName,obj2Str("cd"))
182 self.assertEqual(str2Obj(dss.waitForMonoThrRev(wk)),[7,8,9,10])
185 pool=mp.Pool(processes=nbProc)
186 from NamingService import NamingService
187 asyncResult=pool.map_async(work,[(NamingService.IOROfNS(),i,varName,scopeName) for i in range(nbProc)])
188 print("asyncResult=", asyncResult)
189 self.assertEqual(asyncResult.get(),nbProc*[0]) # <- the big test is here !
190 dsm.removeDataScope(scopeName)
192 def testTransaction2(self):
195 dsm=salome.naming_service.Resolve("/DataServerManager")
196 dsm.cleanScopesInNS()
197 if scopeName in dsm.listScopes():
198 dsm.removeDataScope(scopeName)
199 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
200 self.assertTrue(isCreated)
202 t0=dss.createRdExtVarTransac(varName,obj2Str({"ab":[4,5,6]}))
203 dss.atomicApply([t0])
205 self.assertEqual(dss.getAccessOfVar(varName),"RdExt")
207 self.assertRaises(SALOME.SALOME_Exception,dss.addKeyValueInVarErrorIfAlreadyExisting,varName,obj2Str("ab"),obj2Str([7,8,9,10]))#raises because ab is already a key !
208 t1=dss.addKeyValueInVarErrorIfAlreadyExisting(varName,obj2Str("cd"),obj2Str([7,8,9,10]))
209 dss.atomicApply([t1])
211 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
212 wk=dss.waitForKeyInVar(varName,obj2Str("cd"))
214 self.assertEqual(str2Obj(dss.waitForMonoThrRev(wk)),[7,8,9,10])
215 dsm.removeDataScope(scopeName)
217 def testTransaction3(self):
220 dsm=salome.naming_service.Resolve("/DataServerManager")
221 dsm.cleanScopesInNS()
222 if scopeName in dsm.listScopes():
223 dsm.removeDataScope(scopeName)
224 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
225 self.assertTrue(isCreated)
227 t0=dss.createRdWrVarTransac(varName,obj2Str({"ab":[4,5,6]}))
228 dss.atomicApply([t0])
230 t1=dss.addKeyValueInVarErrorIfAlreadyExisting(varName,obj2Str("cd"),obj2Str([7,8,9,10]))
231 dss.atomicApply([t1])
233 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
235 t2=dss.removeKeyInVarErrorIfNotAlreadyExisting(varName,obj2Str("ab"))
236 dss.atomicApply([t2])
237 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'cd':[7,8,9,10]})
238 dsm.removeDataScope(scopeName)
240 def testTransaction4(self):
243 dsm=salome.naming_service.Resolve("/DataServerManager")
244 dsm.cleanScopesInNS()
245 if scopeName in dsm.listScopes():
246 dsm.removeDataScope(scopeName)
247 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
248 self.assertTrue(isCreated)
250 t0=dss.createRdWrVarTransac(varName,obj2Str({"ab":[4,5,6]}))
251 dss.atomicApply([t0])
253 t1=dss.addKeyValueInVarHard(varName,obj2Str("cd"),obj2Str([7,8,9,10]))
254 dss.atomicApply([t1])
256 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
257 wk,t2=dss.waitForKeyInVarAndKillIt(varName,obj2Str("cd"))
258 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
260 self.assertEqual(str2Obj(dss.waitForMonoThrRev(wk)),[7,8,9,10])
261 dss.atomicApply([t2])
262 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6]})
263 dsm.removeDataScope(scopeName)
265 def testTransaction5(self):
266 """ Like testTransaction2 but without transactions. """
269 dsm=salome.naming_service.Resolve("/DataServerManager")
270 dsm.cleanScopesInNS()
271 if scopeName in dsm.listScopes():
272 dsm.removeDataScope(scopeName)
273 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
274 self.assertTrue(isCreated)
276 t0=dss.createRdExtVarTransac(varName,obj2Str({"ab":[4,5,6]}))
277 dss.atomicApply([t0])
279 self.assertEqual(dss.getAccessOfVar(varName),"RdExt")
280 t1=dss.addMultiKeyValueSession(varName)
281 self.assertEqual(dss.getAccessOfVar(varName),"RdExtInit")
282 self.assertRaises(SALOME.SALOME_Exception,t1.addKeyValueInVarErrorIfAlreadyExistingNow,obj2Str("ab"),obj2Str([7,8,9,10]))#raises because ab is already a key !
283 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6]})
284 wk=dss.waitForKeyInVar(varName,obj2Str("cd"))
285 t1.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("cd"),obj2Str([7,8,9,10]))
287 self.assertEqual(str2Obj(dss.waitForMonoThrRev(wk)),[7,8,9,10])
288 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6]})# it is not a bug ! commit of t1 not done !
289 dss.atomicApply([t1])
290 self.assertEqual(dss.getAccessOfVar(varName),"RdExt")
292 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
293 wk=dss.waitForKeyInVar(varName,obj2Str("cd"))
295 self.assertEqual(str2Obj(dss.waitForMonoThrRev(wk)),[7,8,9,10])
296 keys=[str2Obj(elt) for elt in dss.getAllKeysOfVarWithTypeDict(varName)]
297 self.assertEqual(set(keys),set(['ab','cd']))
298 dsm.removeDataScope(scopeName)
300 def testTransaction6(self):
301 """ Test to test RdWr global vars with transaction"""
304 dsm=salome.naming_service.Resolve("/DataServerManager")
305 dsm.cleanScopesInNS()
306 if scopeName in dsm.listScopes():
307 dsm.removeDataScope(scopeName)
308 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
309 self.assertTrue(isCreated)
311 t0=dss.createWorkingVarTransac(varName,obj2Str({}))
312 a=SalomeSDSClt.GetHandlerFromRef(t0.getVar())
313 self.assertEqual(dss.getAccessOfVar(varName),"RdWr")
316 self.assertEqual(a.local_copy(),{"ab":4})
318 self.assertEqual(a.local_copy(),{"ab":5})
321 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5]})
323 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77]})
324 a.__setitem__("ef",["a","bb"])
325 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb"]})
326 a["ef"].append("ccc")
327 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"]})
329 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"],"gh":{"ab":4,"cd":[5,77],"ef":["a","bb","ccc"]}})
330 a["gh"]["cd"].append(99) ; a["cd"].append(88)
331 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"]}})
332 # WARNING here not problem to overwrite
334 self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77,88],"ef":["a","bb","ccc"],"gh":7})
336 self.assertTrue(isinstance(a,SalomeSDSClt.Dict))
337 self.assertTrue(isinstance(a,SalomeSDSClt.WrappedType))# important for EEM
338 # commit : RdWr->RdOnly
339 dss.atomicApply([t0])
341 self.assertEqual(dss.getAccessOfVar(varName),"RdOnly") # after atomicApply the var is readOnly. Impossible to change its value !
342 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{"ab":4,"cd":[5,77,88],"ef":["a","bb","ccc"],"gh":7})
343 dsm.cleanScopesInNS()
344 del a # very important kill Ref before removingDataScope...
345 if scopeName in dsm.listScopes():
346 dsm.removeDataScope(scopeName)
349 def testTransaction7(self):
350 """Like testTransaction5 but after a recovery."""
353 dsm=salome.naming_service.Resolve("/DataServerManager")
354 dsm.cleanScopesInNS()
355 if scopeName in dsm.listScopes():
356 dsm.removeDataScope(scopeName)
357 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
358 self.assertTrue(isCreated)
360 t0=dss.createRdExtInitVarTransac(varName,obj2Str({"ab":[4,5,6]}))
361 dss.atomicApply([t0])
363 self.assertEqual(dss.getAccessOfVar(varName),"RdExtInit")
364 t1=dss.addMultiKeyValueSession(varName)
365 self.assertEqual(dss.getAccessOfVar(varName),"RdExtInit")
366 t1.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("cd"),obj2Str([7,8,9,10]))
367 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6]})# it is not a bug ! commit of t1 not done !
368 dss.atomicApply([t1])
369 self.assertEqual(dss.getAccessOfVar(varName),"RdExt")
370 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
371 dsm.removeDataScope(scopeName)
374 def testTransaction8(self):
375 """ EDF 16833 and EDF17719 """
376 funcContent="""def comptchev(a,b):
380 dsm=salome.naming_service.Resolve("/DataServerManager")
381 dsm.cleanScopesInNS()
382 if scopeName in dsm.listScopes():
383 dsm.removeDataScope(scopeName)
384 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
385 self.assertTrue(isCreated)
388 value2={'a':1,'c':3,'b':2}
389 value3={'a':1,'c':3,'b':2,'d':4}
392 t0=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent) # sha1 is the key used to compare the initial value
393 dss.atomicApply([t0])
394 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value)
395 t1=dss.addMultiKeyValueSession(varName)
396 t1.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("c"),obj2Str(3))
397 dss.atomicApply([t1])
398 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value2)
399 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
400 dss.atomicApply([t2])
401 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value2) # value2 remains untouched
402 t3=dss.addMultiKeyValueSession(varName)
403 t3.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("d"),obj2Str(4))
404 dss.atomicApply([t3])
405 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value3)
406 t4=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent)
407 self.assertRaises(SALOME.SALOME_Exception,dss.atomicApply,[t4]) # d is in dict pointed by var. Func returns false -> rejected
408 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value3)
409 dsm.removeDataScope(scopeName)
412 def testTransaction9(self):
413 """ EDF 16833 and EDF17719 : use case 2. Trying to createRdExt during add key session"""
414 funcContent="""def comptchev(a,b):
418 dsm=salome.naming_service.Resolve("/DataServerManager")
419 dsm.cleanScopesInNS()
420 if scopeName in dsm.listScopes():
421 dsm.removeDataScope(scopeName)
422 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
423 self.assertTrue(isCreated)
426 value2={'a':1,'c':3,'b':2}
429 t0=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent)
430 dss.atomicApply([t0])
431 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value)
432 t1=dss.addMultiKeyValueSession(varName)
433 t2=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent)
434 dss.atomicApply([t2])
435 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value)
436 t1.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("c"),obj2Str(3))
437 dss.atomicApply([t1])
438 self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value2)
439 dsm.removeDataScope(scopeName)
443 def testLockToDump(self):
444 """ Test to check that holdRequests method. This method wait for clean server status and hold it until activeRequests is called.
445 Warning this method expects a not overloaded machine to be run because test is based on ellapse time.
450 dsm=salome.naming_service.Resolve("/DataServerManager")
451 dsm.cleanScopesInNS()
452 if scopeName in dsm.listScopes():
453 dsm.removeDataScope(scopeName)
454 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
455 self.assertTrue(isCreated)
456 cv=mp.Condition(mp.Lock())
457 cv2=mp.Condition(mp.Lock()) # sharedNum & cv2 & cv3 for the barrier
458 cv3=mp.Condition(mp.Lock())
459 sharedNum=mp.Value('b',False)
460 p=mp.Process(target=func_test7,args=(scopeName,cv,cv2,cv3,sharedNum))
463 dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
464 self.assertTrue(not isCreated)
465 t0=dss.createRdWrVarTransac(varName,obj2Str(zeObj))
466 dss.atomicApply([t0])
467 rs=dss.getRequestSwitcher()
468 self.assertTrue(not isCreated)
471 if not sharedNum.value:
473 sharedNum.value=False
478 rs.holdRequests() # The aim of the test
479 self.assertEqual(rs.listVars(),[varName]) # call whereas holdRequest is called
480 time.sleep(nbOfSecWait)
481 rs.activeRequests() # The aim of the test
482 ######### micro-test3 - check that holdRequests is able to wait for a non finished job
486 time.sleep(0.01) # let main proc the priority
487 rs.holdRequests() # the aim of the test is here. main process is occupied 1s -> holdRequests is Expected to wait
488 s=(datetime.now()-s).total_seconds()
489 self.assertTrue(str2Obj(rs.fetchSerializedContent(varName))==zeObj) # call whereas holdRequest is called
491 self.assertTrue(s>=0.99*nbOfSecWait and s<nbOfSecWait*1.01) # expect to be not locked
494 dsm.removeDataScope(scopeName)
497 def testShutdownScopes(self):
498 """ Test shutdownScopes.
501 dss, isCreated = salome.dsm.giveADataScopeTransactionCalled('scope0')
502 t0 = dss.createRdExtVarTransac('a', obj2Str({}))
503 dss.atomicApply([t0])
504 salome.dsm.shutdownScopes() # no exception expected
509 if __name__=="__main__":
510 with salome.SessionContextManager():