Salome HOME
WIP
[modules/kernel.git] / src / SALOMESDS / TestSalomeSDS.py
index a4302f27cb3d5bd6f684e3d4ef48d4a48d48ee6d..d61a9e1ed3bc6f249bcfb301f9026ee693efee79 100644 (file)
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+# Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -26,8 +26,11 @@ import unittest
 import pickle
 import gc
 import time
+from datetime import datetime
 import multiprocessing as mp
 
+nbOfSecWait=1.
+
 def obj2Str(obj):
   return pickle.dumps(obj,pickle.HIGHEST_PROTOCOL)
 def str2Obj(strr):
@@ -40,7 +43,7 @@ def generateKey(varName,scopeName):
   time.sleep(3)
   dss.atomicApply([t])
 def work(t):
-  i,varName,scopeName=t
+  IORNS,i,varName,scopeName=t
   if i==0:
     generateKey(varName,scopeName)
     return 0
@@ -48,16 +51,51 @@ def work(t):
     import TestSalomeSDSHelper0
     import os,subprocess
     fname=os.path.splitext(TestSalomeSDSHelper0.__file__)[0]+".py"
-    proc=subprocess.Popen(["python",fname],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
+    proc = subprocess.Popen(["python3", fname, IORNS], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     out,err=proc.communicate()
     if proc.returncode!=0:
+      print("-------------- work -----------")
       print(out)
       print(err)
+      print("~~~~~~~~~~~~~~ work ~~~~~~~~~~~")
     return proc.returncode
-
+  
+def func_test7(scopeName,cv,cv2,cv3,sharedNum):
+    salome.salome_init()
+    varName="a"
+    zeValue={"ab":[4,5,6]}
+    dsm=salome.naming_service.Resolve("/DataServerManager")
+    dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName) # should be suspended nbOfSecWait s by main process
+    assert(not isCreated)
+    ######### micro-test1 - check that all requests are suspended
+    ######## Barrier
+    with cv2:
+      cv2.notify_all()
+      sharedNum.value=True
+    with cv3:
+      cv3.wait()
+    ####### End Barrier
+    s=datetime.now()
+    t0=dss.createRdWrVarTransac(varName,obj2Str(zeValue))
+    s=(datetime.now()-s).total_seconds()
+    assert(s>=0.99*nbOfSecWait and s<nbOfSecWait*1.01) # expect to wait nearly nbOfSecWait seconds
+    dss.atomicApply([t0])
+    ######### end of micro-test1
+    ######### micro-test2 - after activeRequests everything work well
+    s=datetime.now()
+    st=dss.fetchSerializedContent(varName)
+    assert(str2Obj(st)==zeValue)
+    s=(datetime.now()-s).total_seconds()
+    assert(s>=0. and s<0.05) # expect to be not locked
+    ######### end of micro-test2
+    with cv:
+      cv.notify_all()
+    dss.takeANap(nbOfSecWait) # emulate a DataServer occupation
+    pass
+  
 class SalomeSDSTest(unittest.TestCase):
   
-  def testList1(self):
+  def tessList1(self):
     a=SalomeSDSClt.CreateRdExtGlobalVar([],"a","Scope0")
     self.assertEqual(a.local_copy(),[])
     a.append(5)
@@ -76,7 +114,7 @@ class SalomeSDSTest(unittest.TestCase):
     a.ptr().getMyDataScopeServer().deleteVar("a")
     pass
   
-  def testDict1(self):
+  def tessDict1(self):
     a=SalomeSDSClt.CreateRdExtGlobalVar({},"a","Scope0")
     a["ab"]=4
     self.assertEqual(a.local_copy(),{"ab":4})
@@ -97,7 +135,7 @@ class SalomeSDSTest(unittest.TestCase):
     a.ptr().getMyDataScopeServer().deleteVar("a")
     pass
 
-  def testReadOnly1(self):
+  def tessReadOnly1(self):
     a=SalomeSDSClt.CreateRdOnlyGlobalVar({"ab":4,"cd":[5,77]},"a","Scope0")
     self.assertEqual(a.local_copy(),{"ab":4,"cd":[5,77]})
     self.assertRaises(Exception,a.__getitem__,"ab")
@@ -128,11 +166,13 @@ class SalomeSDSTest(unittest.TestCase):
     #
     nbProc=8
     pool=mp.Pool(processes=nbProc)
-    asyncResult=pool.map_async(work,[(i,varName,scopeName) for i in range(nbProc)])
+    from  NamingService import NamingService
+    asyncResult=pool.map_async(work,[(NamingService.IOROfNS(),i,varName,scopeName) for i in range(nbProc)])
+    print("asyncResult=", asyncResult)
     self.assertEqual(asyncResult.get(),nbProc*[0]) # <- the big test is here !
     dsm.removeDataScope(scopeName)
 
-  def testTransaction2(self):
+  def tessTransaction2(self):
     scopeName="Scope1"
     varName="a"
     dsm=salome.naming_service.Resolve("/DataServerManager")
@@ -156,7 +196,7 @@ class SalomeSDSTest(unittest.TestCase):
     wk.waitFor()
     self.assertEqual(str2Obj(dss.waitForMonoThrRev(wk)),[7,8,9,10])
 
-  def testTransaction3(self):
+  def tessTransaction3(self):
     scopeName="Scope1"
     varName="a"
     dsm=salome.naming_service.Resolve("/DataServerManager")
@@ -178,7 +218,7 @@ class SalomeSDSTest(unittest.TestCase):
     dss.atomicApply([t2])
     self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'cd':[7,8,9,10]})
 
-  def testTransaction4(self):
+  def tessTransaction4(self):
     scopeName="Scope1"
     varName="a"
     dsm=salome.naming_service.Resolve("/DataServerManager")
@@ -202,7 +242,7 @@ class SalomeSDSTest(unittest.TestCase):
     dss.atomicApply([t2])
     self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6]})
 
-  def testTransaction5(self):
+  def tessTransaction5(self):
     """ Like testTransaction2 but without transactions. """
     scopeName="Scope1"
     varName="a"
@@ -234,9 +274,9 @@ class SalomeSDSTest(unittest.TestCase):
     wk.waitFor()
     self.assertEqual(str2Obj(dss.waitForMonoThrRev(wk)),[7,8,9,10])
     keys=[str2Obj(elt) for elt in dss.getAllKeysOfVarWithTypeDict(varName)]
-    self.assertEqual(keys,['ab','cd'])
+    self.assertEqual(set(keys),set(['ab','cd']))
 
-  def testTransaction6(self):
+  def tessTransaction6(self):
     """ Test to test RdWr global vars with transaction"""
     scopeName="Scope1"
     varName="a"
@@ -285,7 +325,7 @@ class SalomeSDSTest(unittest.TestCase):
       dsm.removeDataScope(scopeName)
     pass
 
-  def testTransaction7(self):
+  def tessTransaction7(self):
     """Like testTransaction5 but after a recovery."""
     scopeName="Scope1"
     varName="a"
@@ -309,11 +349,133 @@ class SalomeSDSTest(unittest.TestCase):
     self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),{'ab':[4,5,6],'cd':[7,8,9,10]})
     pass
 
+  def tessTransaction8(self):
+    """ EDF 16833 and EDF17719 """
+    funcContent="""def comptchev(a,b):
+    return "d" not in a
+"""
+    scopeName="ScopePP"
+    dsm=salome.naming_service.Resolve("/DataServerManager")
+    dsm.cleanScopesInNS()
+    if scopeName in dsm.listScopes():
+        dsm.removeDataScope(scopeName)
+    dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
+    self.assertTrue(isCreated)
+
+    value={"a":1,"b":2}
+    value2={'a':1,'c':3,'b':2}
+    value3={'a':1,'c':3,'b':2,'d':4}
+
+    varName="abc"
+    t0=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent) # sha1 is the key used to compare the initial value
+    dss.atomicApply([t0])
+    self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value)
+    t1=dss.addMultiKeyValueSession(varName)
+    t1.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("c"),obj2Str(3))
+    dss.atomicApply([t1])
+    self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value2)
+    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
+    dss.atomicApply([t2])
+    self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value2) # value2 remains untouched
+    t3=dss.addMultiKeyValueSession(varName)
+    t3.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("d"),obj2Str(4))
+    dss.atomicApply([t3])
+    self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value3)
+    t4=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent)
+    self.assertRaises(SALOME.SALOME_Exception,dss.atomicApply,[t4]) # d is in dict pointed by var. Func returns false -> rejected
+    self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value3)
+    pass
+  
+  def tessTransaction9(self):
+    """ EDF 16833 and EDF17719 : use case 2. Trying to createRdExt during add key session"""
+    funcContent="""def comptchev(a,b):
+    return a==b
+"""
+    scopeName="ScopePP"
+    dsm=salome.naming_service.Resolve("/DataServerManager")
+    dsm.cleanScopesInNS()
+    if scopeName in dsm.listScopes():
+        dsm.removeDataScope(scopeName)
+    dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
+    self.assertTrue(isCreated)
+
+    value={"a":1,"b":2}
+    value2={'a':1,'c':3,'b':2}
+
+    varName="abc"
+    t0=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent)
+    dss.atomicApply([t0])
+    self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value)
+    t1=dss.addMultiKeyValueSession(varName)
+    t2=dss.createRdExtVarFreeStyleTransac(varName,obj2Str(value),funcContent)
+    dss.atomicApply([t2])
+    self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value)
+    t1.addKeyValueInVarErrorIfAlreadyExistingNow(obj2Str("c"),obj2Str(3))
+    dss.atomicApply([t1])
+    self.assertEqual(str2Obj(dss.fetchSerializedContent(varName)),value2)
+    pass
+
+    
+  def tessLockToDump(self):
+    """ Test to check that holdRequests method. This method wait for clean server status and hold it until activeRequests is called.
+    Warning this method expects a not overloaded machine to be run because test is based on ellapse time.
+    """
+    scopeName="Scope1"
+    varName="ab"
+    zeObj={"ab":[5,6]}
+    dsm=salome.naming_service.Resolve("/DataServerManager")
+    dsm.cleanScopesInNS()
+    if scopeName in dsm.listScopes():
+        dsm.removeDataScope(scopeName)
+    dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
+    self.assertTrue(isCreated)
+    cv=mp.Condition(mp.Lock())
+    cv2=mp.Condition(mp.Lock()) # sharedNum & cv2 & cv3 for the barrier
+    cv3=mp.Condition(mp.Lock())
+    sharedNum=mp.Value('b',False)
+    p=mp.Process(target=func_test7,args=(scopeName,cv,cv2,cv3,sharedNum))
+    p.start()
+    #
+    dss,isCreated=dsm.giveADataScopeTransactionCalled(scopeName)
+    self.assertTrue(not isCreated)
+    t0=dss.createRdWrVarTransac(varName,obj2Str(zeObj))
+    dss.atomicApply([t0])
+    rs=dss.getRequestSwitcher()
+    self.assertTrue(not isCreated)
+    ######## Barrier
+    with cv2:
+      if not sharedNum.value:
+        cv2.wait()
+      sharedNum.value=False
+      pass
+    with cv3:
+      cv3.notify_all()
+    ####### End Barrier
+    rs.holdRequests() # The aim of the test
+    self.assertEqual(rs.listVars(),[varName]) # call whereas holdRequest is called
+    time.sleep(nbOfSecWait)
+    rs.activeRequests() # The aim of the test
+    ######### micro-test3 - check that holdRequests is able to wait for a non finished job
+    with cv:
+      cv.wait()
+      s=datetime.now()
+      time.sleep(0.01) # let main proc the priority
+      rs.holdRequests() # the aim of the test is here. main process is occupied 1s -> holdRequests is Expected to wait
+      s=(datetime.now()-s).total_seconds()
+      self.assertTrue(str2Obj(rs.fetchSerializedContent(varName))==zeObj) # call whereas holdRequest is called
+      rs.activeRequests()
+      self.assertTrue(s>=0.99*nbOfSecWait and s<nbOfSecWait*1.01) # expect to be not locked
+    # finishing
+    p.join()
+    pass
+
   def setUp(self):
-    salome.salome_init()
+    #salome.salome_init()
+    salome.salome_init_without_session()
     pass
   
   pass
 
-unittest.main()
+if __name__=="__main__":
+  unittest.main()