From 694325ec92a2ab7cdae20f80205dfec6d625b8c8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?C=C3=A9dric=20Aguerre?= Date: Fri, 14 Mar 2014 17:29:30 +0100 Subject: [PATCH] unit tests for concurrent sessions --- bin/appliskel/tests/CMakeLists.txt | 2 +- .../tests/concurrentSession/CMakeLists.txt | 21 +---- ...entSession.py => TestConcurrentSession.py} | 62 +++++++++---- .../concurrentSession/TestMinimalExample.py | 92 +++++++++++++------ .../concurrentSession/usecase_concurrent.sh | 67 ++++++++++++++ bin/searchFreePort.py | 1 - 6 files changed, 178 insertions(+), 67 deletions(-) rename bin/appliskel/tests/concurrentSession/{testConcurrentSession.py => TestConcurrentSession.py} (56%) create mode 100755 bin/appliskel/tests/concurrentSession/usecase_concurrent.sh diff --git a/bin/appliskel/tests/CMakeLists.txt b/bin/appliskel/tests/CMakeLists.txt index 4d96e416a..602a867f9 100644 --- a/bin/appliskel/tests/CMakeLists.txt +++ b/bin/appliskel/tests/CMakeLists.txt @@ -17,5 +17,5 @@ # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # -#ADD_SUBDIRECTORY(concurrentSession) +ADD_SUBDIRECTORY(concurrentSession) ADD_SUBDIRECTORY(launcher) diff --git a/bin/appliskel/tests/concurrentSession/CMakeLists.txt b/bin/appliskel/tests/concurrentSession/CMakeLists.txt index 029ff882f..7ffa4027e 100644 --- a/bin/appliskel/tests/concurrentSession/CMakeLists.txt +++ b/bin/appliskel/tests/concurrentSession/CMakeLists.txt @@ -17,24 +17,9 @@ # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # -include(CTest) -ENABLE_TESTING() +FILE(GLOB py_scripts "${CMAKE_CURRENT_SOURCE_DIR}/*.py") +FILE(GLOB sh_scripts "${CMAKE_CURRENT_SOURCE_DIR}/*.sh") -# define environment for running tests -SET(PYTHON_VERSION ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}) +LIST(APPEND scripts ${py_scripts} ${sh_scripts}) -SET(THIS_PYTHONPATH ${CMAKE_SOURCE_DIR}/bin:$ENV{PYTHONPATH}) -#SET(THIS_LD_LIBRARY_PATH $ENV{LD_LIBRARY_PATH}) - -# add tests (use make test to run) -FILE(GLOB tests "${CMAKE_CURRENT_SOURCE_DIR}/Test*.py") -FOREACH(file ${tests}) - GET_FILENAME_COMPONENT(testname ${file} NAME_WE) - ADD_TEST(${testname} ${PYTHON_EXECUTABLE} "${file}") -# SET_PROPERTY(TEST ${testname} APPEND PROPERTY ENVIRONMENT PYTHONPATH=${THIS_PYTHONPATH} LD_LIBRARY_PATH=${THIS_LD_LIBRARY_PATH}) - SET_PROPERTY(TEST ${testname} APPEND PROPERTY ENVIRONMENT PYTHONPATH=${THIS_PYTHONPATH}) -ENDFOREACH() - -# install Python scripts -FILE(GLOB scripts "${CMAKE_CURRENT_SOURCE_DIR}/*.py") SALOME_INSTALL_SCRIPTS("${scripts}" ${SALOME_INSTALL_SCRIPT_SCRIPTS}/appliskel/tests/concurrentSession) diff --git a/bin/appliskel/tests/concurrentSession/testConcurrentSession.py b/bin/appliskel/tests/concurrentSession/TestConcurrentSession.py similarity index 56% rename from bin/appliskel/tests/concurrentSession/testConcurrentSession.py rename to bin/appliskel/tests/concurrentSession/TestConcurrentSession.py index 93eeee406..5f8376a08 100644 --- a/bin/appliskel/tests/concurrentSession/testConcurrentSession.py +++ b/bin/appliskel/tests/concurrentSession/TestConcurrentSession.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE # # This library is free software; you can redistribute it and/or @@ -18,48 +17,68 @@ # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # +import unittest +import tempfile + import os import sys -import unittest -import multiprocessing import imp +from cStringIO import StringIO +import multiprocessing -def unwrap_self_session(arg, **kwarg): - return TestConcurrentLaunch.session(*arg, **kwarg) -# class TestConcurrentLaunch(unittest.TestCase): - @classmethod - def setUpClass(cls): + def setUp(self): # Initialize path to SALOME application path_to_launcher = os.getenv("SALOME_LAUNCHER") appli_dir = os.path.dirname(path_to_launcher) - cls.envd_dir = os.path.join(appli_dir, "env.d") # Configure session startup - cls.SALOME = imp.load_source("SALOME", os.path.join(appli_dir,"salome")) - #cls.SALOME_args = ["shell", "--config="+cls.envd_dir] - cls.SALOME_args = ["--config="+cls.envd_dir] + self.SALOME = imp.load_source("SALOME", os.path.join(appli_dir,"salome")) + self.SALOME_appli_args = ["start", "-t"] + self.SALOME_shell_args = ["shell"] # - @classmethod - def tearDownClass(cls): - args = ["killall", "--config="+cls.envd_dir] - cls.SALOME.main(args) + def tearDown(self): pass # + def appli(self, args=[]): + self.SALOME.main(self.SALOME_appli_args + args) + # def session(self, args=[]): - self.SALOME.main(self.SALOME_args + args) + self.SALOME.main(self.SALOME_shell_args + args) # def test01_SingleSession(self): print "** Testing single session **" - self.session() + self.session(["hello.py"]) # def test02_MultiSession(self): print "** Testing multi sessions **" + jobs = [] + for i in range(3): + p = multiprocessing.Process(target=self.session, args=(["hello.py"],)) + jobs.append(p) + p.start() + for j in jobs: + j.join() + # + def test03_SingleAppli(self): + print "** Testing single appli **" + current_directory = os.path.dirname(os.path.abspath(__file__)) + session_log = tempfile.NamedTemporaryFile(prefix='session_', suffix='.log') + self.appli(["--ns-port-log=%s"%session_log.name]) + port_number = None + with open(session_log.name, "r") as f: + port_number = f.readline() + self.session(["hello.py"]) + self.session(["-p", port_number, "killSalomeWithPort.py", "args:%s"%port_number]) + session_log.close() + # + def test04_MultiAppli(self): + print "** Testing multi appli **" jobs = [] for i in range(3): - p = multiprocessing.Process(target=unwrap_self_session, args=([self],)) + p = multiprocessing.Process(target=self.test03_SingleAppli) jobs.append(p) p.start() @@ -68,12 +87,15 @@ class TestConcurrentLaunch(unittest.TestCase): # # - if __name__ == "__main__": path_to_launcher = os.getenv("SALOME_LAUNCHER") if not path_to_launcher: msg = "Error: please set SALOME_LAUNCHER variable to the salome command of your application folder." raise Exception(msg) + if not os.path.isfile("hello.py"): + with open("hello.py", "w") as f: + f.write("print 'Hello!'") + unittest.main() # diff --git a/bin/appliskel/tests/concurrentSession/TestMinimalExample.py b/bin/appliskel/tests/concurrentSession/TestMinimalExample.py index 8b38d582d..b740cdd00 100644 --- a/bin/appliskel/tests/concurrentSession/TestMinimalExample.py +++ b/bin/appliskel/tests/concurrentSession/TestMinimalExample.py @@ -18,33 +18,34 @@ # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # -from PortManager import getPort, releasePort, stopServer +import os import sys import multiprocessing import unittest -def port_reservation(prefered=None, test=None, expected=None): +def port_reservation(obtained_ports, prefered=None, test=None, expected=None): + from PortManager import getPort if prefered: port = getPort(prefered) else: port = getPort() - print "port = %s"%port + print "obtained port = %s"%port + + obtained_ports.put(port) if expected: - print "expected = %s"%expected - test.assertTrue(port == expected) + test.assertTrue(port == expected, "used = %s, expected = %s"%(port, expected)) # class TestMinimalExample(unittest.TestCase): - @classmethod - def tearDownClass(cls): - stopServer() - stopServer() # no effect - # def testSequential(self): - print "BEGIN testSequential" + from PortManager import releasePort, getBusyPorts + print "\nBEGIN testSequential" + print "Busy ports", getBusyPorts() + obtained_ports = multiprocessing.Queue() + processes = [ - multiprocessing.Process(target=port_reservation) + multiprocessing.Process(target=port_reservation, args=(obtained_ports,)) for i in range(3) ] @@ -54,51 +55,66 @@ class TestMinimalExample(unittest.TestCase): for p in processes: p.join() + print "Busy ports", getBusyPorts() # Try to get specific port number - expected = 2872 - p = multiprocessing.Process(target=port_reservation, args=(2872, self,expected,)) + p = multiprocessing.Process(target=port_reservation, args=(obtained_ports, 2872, self, 2872,)) p.start() p.join() # Try to get specific port number - p = multiprocessing.Process(target=port_reservation, args=(2812, self,)) + p = multiprocessing.Process(target=port_reservation, args=(obtained_ports, 2812, self,)) + p.start() + p.join() + + # Try to get specific port number + p = multiprocessing.Process(target=port_reservation, args=(obtained_ports, 2812, self,)) p.start() p.join() # Release port + print "release port 2812" p = multiprocessing.Process(target=releasePort, args=(2812,)) p.start() p.join() # Try to get specific port number - expected = 2812 - p = multiprocessing.Process(target=port_reservation, args=(2812, self,expected,)) + p = multiprocessing.Process(target=port_reservation, args=(obtained_ports, 2812, self, 2812,)) p.start() p.join() + # Release ports + print "Busy ports", getBusyPorts() + while not obtained_ports.empty(): + port = obtained_ports.get() + print "release port", port + p = multiprocessing.Process(target=releasePort, args=(port,)) + p.start() + p.join() + print "END testSequential" # + def testConcurrent(self): - print "BEGIN testConcurrent" + from PortManager import releasePort, getBusyPorts + print "\nBEGIN testConcurrent" + print "Busy ports", getBusyPorts() + obtained_ports = multiprocessing.Queue() processes = [ - multiprocessing.Process(target=port_reservation) + multiprocessing.Process(target=port_reservation, args=(obtained_ports,)) + for i in range(3) ] # Try to get specific port number - p = multiprocessing.Process(target=port_reservation, args=(2852,)) + p = multiprocessing.Process(target=port_reservation, args=(obtained_ports, 2872, self, 2872,)) processes.append(p) # Try to get specific port number - p = multiprocessing.Process(target=port_reservation, args=(2812,)) - processes.append(p) - - # Release port - p = multiprocessing.Process(target=releasePort, args=(2812,)) + p = multiprocessing.Process(target=port_reservation, args=(obtained_ports, 2812,)) processes.append(p) # Try to get specific port number - p = multiprocessing.Process(target=port_reservation, args=(2812,)) + p = multiprocessing.Process(target=port_reservation, args=(obtained_ports, 2812,)) processes.append(p) for p in processes: @@ -107,8 +123,30 @@ class TestMinimalExample(unittest.TestCase): for p in processes: p.join() + # Release ports + print "Busy ports", getBusyPorts() + while not obtained_ports.empty(): + port = obtained_ports.get() + print "release port", port + p = multiprocessing.Process(target=releasePort, args=(port,)) + p.start() + p.join() + print "END testConcurrent" # # -unittest.main() +if __name__ == "__main__": + omniorb_user_path = os.getenv("OMNIORB_USER_PATH") + if not omniorb_user_path: + msg = "Error: please set OMNIORB_USER_PATH variable to the salome KERNEL install folder." + raise Exception(msg) + + try: + import PortManager + except ImportError: + msg = "Error: can't import PortManager; please check PYTHONPATH variable." + raise Exception(msg) + + unittest.main() +# diff --git a/bin/appliskel/tests/concurrentSession/usecase_concurrent.sh b/bin/appliskel/tests/concurrentSession/usecase_concurrent.sh new file mode 100755 index 000000000..a730f4793 --- /dev/null +++ b/bin/appliskel/tests/concurrentSession/usecase_concurrent.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +echo "This is a script that can be run concurrently." +echo "It takes as single argument the number of concurrent executions:" +echo "Usage: " $0 "" +echo +echo "Here is what executed code contents looks like:" +echo " - do some stuff" +echo " - run SALOME in terminal mode, and log port number to a file" +echo " - run some scripts (Python, binary), each in a dedicated SALOME session on a specific port" +echo " - do some stuff" +echo + + +if [ $# != 2 ]; then + echo "Usage:" $0 " " + exit 1 +fi + +NB_COMP=$1 +OUTPUT_FOLDER=$2 +BASE_DIR=`pwd` + +if [ "x${SALOME_APPLI_FOLDER}" == "x" ]; then + echo "SALOME_APPLI_FOLDER variable is not set (or empty)." + echo "Try to locate SALOME launcher in current directory." + SALOME_APPLI_FOLDER=`pwd` + if ! [ -f ${SALOME_APPLI_FOLDER}/salome ]; then + echo "Unable to locate salome command." + exit 1 + fi +fi + +run_command() { + WORK_DIR=`pwd` # a pushd has been done before calling this function + echo "Run command in folder:" ${WORK_DIR} + ${SALOME_APPLI_FOLDER}/salome start -t --ns-port-log=${WORK_DIR}/session.log + ${SALOME_APPLI_FOLDER}/salome shell -p `cat ${WORK_DIR}/session.log` ${SALOME_APPLI_FOLDER}/bin/salome/waitContainers.py + ${SALOME_APPLI_FOLDER}/salome shell -p `cat ${WORK_DIR}/session.log` ${BASE_DIR}/hello.py + ${SALOME_APPLI_FOLDER}/salome shell -p `cat ${WORK_DIR}/session.log` ${SALOME_APPLI_FOLDER}/bin/salome/killSalomeWithPort.py args:`cat ${WORK_DIR}/session.log` + echo "Execution terminated in folder:" ${WORK_DIR} +} + + +# make hello.py +echo " +#!/usr/bin/env python +print 'Hello\!' +" > ${BASE_DIR}/hello.py + +# Build output folders +typeset -i i=${NB_COMP} +while (( $i > 0 )) +do + mkdir -p ${OUTPUT_FOLDER}/execution_$i + let "i=i-1" +done + +# Start execution +typeset -i i=${NB_COMP} +while (( $i > 0 )) +do + pushd ${OUTPUT_FOLDER}/execution_$i > /dev/null + run_command & + popd > /dev/null + let "i=i-1" +done diff --git a/bin/searchFreePort.py b/bin/searchFreePort.py index 99005ef9d..999a952e9 100644 --- a/bin/searchFreePort.py +++ b/bin/searchFreePort.py @@ -158,7 +158,6 @@ def __savePortToFile(args): if args.has_key('ns_port_log_file'): omniorbUserPath = os.getenv("OMNIORB_USER_PATH") file_name = os.path.join(omniorbUserPath, args["ns_port_log_file"]) - print file_name, os.environ['NSPORT'] with open(file_name, "w") as f: f.write(os.environ['NSPORT']) # -- 2.39.2