From 93bf864614a7b14bc12b29e588382285c80fe7d5 Mon Sep 17 00:00:00 2001 From: Ovidiu Mircescu Date: Wed, 26 Nov 2014 18:39:54 +0100 Subject: [PATCH] Add tests for SalomeLauncher --- src/Launcher/CMakeLists.txt | 4 + src/Launcher/Test/CMakeLists.txt | 28 +++ src/Launcher/Test/test_launcher.py | 316 +++++++++++++++++++++++++++++ src/UnitTests/prepare_test.py | 117 +++++++++++ 4 files changed, 465 insertions(+) create mode 100644 src/Launcher/Test/CMakeLists.txt create mode 100755 src/Launcher/Test/test_launcher.py create mode 100755 src/UnitTests/prepare_test.py diff --git a/src/Launcher/CMakeLists.txt b/src/Launcher/CMakeLists.txt index 4a14d0496..3f5534a98 100755 --- a/src/Launcher/CMakeLists.txt +++ b/src/Launcher/CMakeLists.txt @@ -17,6 +17,10 @@ # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # +IF(SALOME_BUILD_TESTS) + ADD_SUBDIRECTORY(Test) +ENDIF(SALOME_BUILD_TESTS) + INCLUDE_DIRECTORIES( ${LIBXML2_INCLUDE_DIR} ${OMNIORB_INCLUDE_DIR} diff --git a/src/Launcher/Test/CMakeLists.txt b/src/Launcher/Test/CMakeLists.txt new file mode 100644 index 000000000..67563f7a1 --- /dev/null +++ b/src/Launcher/Test/CMakeLists.txt @@ -0,0 +1,28 @@ +# Copyright (C) 2012-2014 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +# --- rules --- + +IF(NOT WIN32) + ADD_TEST(NAME SalomeLauncher + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../../UnitTests/prepare_test.py + ${CMAKE_CURRENT_SOURCE_DIR}/test_launcher.py + -d KERNEL_ROOT_DIR=${CMAKE_INSTALL_PREFIX} + ) +ENDIF() diff --git a/src/Launcher/Test/test_launcher.py b/src/Launcher/Test/test_launcher.py new file mode 100755 index 000000000..2196ae6a3 --- /dev/null +++ b/src/Launcher/Test/test_launcher.py @@ -0,0 +1,316 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +import unittest +import os +import sys +import time + +# Test of SalomeLauncher. +# This test should be run in the salome environment, using "salome shell" +# If YACS_ROOT_DIR is not set, the test of submitting a YACS schema will be +# skiped. +class TestCompo(unittest.TestCase): + @classmethod + def setUpClass(cls): + # Prepare the test directory + import shutil + cls.test_dir = os.path.join(os.getcwd(), "test_dir") + cls.suffix = time.strftime("-%Y-%m-%d-%H-%M-%S") + shutil.rmtree(cls.test_dir, ignore_errors=True) + os.mkdir(cls.test_dir) + + ############################## + # test of python_salome job + ############################## + def test_salome_py_job(self): + case_test_dir = os.path.join(TestCompo.test_dir, "salome_py") + os.mkdir(case_test_dir) + + old_dir = os.getcwd() + os.chdir(case_test_dir) + + # job script + script_file = "myScript.py" + job_script_file = os.path.join(case_test_dir, script_file) + script_text = """#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# verify import salome +import salome +salome.salome_init() + +f = open('result.txt', 'w') +f.write("Salut!") +f.close() + +import os +os.mkdir("subdir") +f = open(os.path.join("subdir",'autre.txt'), 'w') +f.write("Hello!") +f.close() +""" + f = open(job_script_file, "w") + f.write(script_text) + f.close() + + local_result_dir = os.path.join(case_test_dir, "result_simple_py_job") + job_params = salome.JobParameters() + job_params.job_name = "MyJob" + job_params.job_type = "python_salome" + job_params.job_file = job_script_file + job_params.in_files = [] + job_params.out_files = ["result.txt", "subdir"] + job_params.result_directory = local_result_dir + job_params.resource_required = salome.ResourceParameters() + job_params.resource_required.nb_proc = 1 + + job_params.work_directory = "/tmp/job_salome_py" + self.suffix + + launcher = salome.naming_service.Resolve('/SalomeLauncher') + job_id = launcher.createJob(job_params) + + launcher.launchJob(job_id) + + import time + jobState = launcher.getJobState(job_id) + print "Job %d state: %s" % (job_id,jobState) + while jobState != "FINISHED" and jobState != "FAILED" : + time.sleep(5) + jobState = launcher.getJobState(job_id) + print "Job %d state: %s" % (job_id,jobState) + pass + + self.assertEqual(jobState, "FINISHED") + + # getJobResults to default directory (result_directory) + launcher.getJobResults(job_id, "") + try: + f = open(os.path.join(local_result_dir, "result.txt"), 'r') + text = f.read() + f.close() + self.assertEqual(text, "Salut!") + except IOError,ex: + self.fail("IO exception:" + str(ex)); + + try: + f = open(os.path.join(local_result_dir, "subdir", "autre.txt"), 'r') + text = f.read() + f.close() + self.assertEqual(text, "Hello!") + except IOError,ex: + self.fail("IO exception:" + str(ex)); + + # getJobResults to a specific directory + mydir = os.path.join(case_test_dir, "custom_result_dir") + launcher.getJobResults(job_id, mydir) + try: + f = open(os.path.join(mydir, "result.txt"), 'r') + text = f.read() + f.close() + self.assertEqual(text, "Salut!") + except IOError,ex: + self.fail("IO exception:" + str(ex)); + + try: + f = open(os.path.join(mydir, "subdir", "autre.txt"), 'r') + text = f.read() + f.close() + self.assertEqual(text, "Hello!") + except IOError,ex: + self.fail("IO exception:" + str(ex)); + pass + + os.chdir(old_dir) + + ############################## + # test of command job type + ############################## + def test_command(self): + case_test_dir = os.path.join(TestCompo.test_dir, "command") + os.mkdir(case_test_dir) + + # job script + data_file = "in.txt" + script_file = "myEnvScript.py" + script_text = """#! /usr/bin/env python +# -*- coding: utf-8 -*- + +import os,sys + +text_result = os.getenv("ENV_TEST_VAR","") + +f = open('result.txt', 'w') +f.write(text_result) +f.close() + +in_f = open("in.txt", "r") +in_text = in_f.read() +in_f.close() + +os.mkdir("subdir") +f = open(os.path.join("subdir",'altul.txt'), 'w') +f.write(in_text) +f.close() +""" + abs_script_file = os.path.join(case_test_dir, script_file) + f = open(abs_script_file, "w") + f.write(script_text) + f.close() + os.chmod(abs_script_file, 0o755) + + #environement script + env_file = "myEnv.sh" + env_text = """export ENV_TEST_VAR="expected" +""" + f = open(os.path.join(case_test_dir, env_file), "w") + f.write(env_text) + f.close() + + # write data file + f = open(os.path.join(case_test_dir, data_file), "w") + f.write("expected data") + f.close() + + # job params + local_result_dir = os.path.join(case_test_dir, "resultats_env") + job_params = salome.JobParameters() + job_params.job_name = "CommandJob" + job_params.job_type = "command" + job_params.job_file = script_file + job_params.env_file = env_file + job_params.in_files = [data_file] + job_params.out_files = ["result.txt", "subdir"] + job_params.local_directory = case_test_dir + job_params.result_directory = local_result_dir + job_params.resource_required = salome.ResourceParameters() + job_params.resource_required.nb_proc = 1 + job_params.work_directory = "/tmp/command_job" + self.suffix + + # create and launch the job + launcher = salome.naming_service.Resolve('/SalomeLauncher') + job_id = launcher.createJob(job_params) + launcher.launchJob(job_id) + + # wait for the end of the job + import time + jobState = launcher.getJobState(job_id) + print "Job %d state: %s" % (job_id,jobState) + while jobState != "FINISHED" and jobState != "FAILED" : + time.sleep(3) + jobState = launcher.getJobState(job_id) + print "Job %d state: %s" % (job_id,jobState) + pass + + # verify the results + self.assertEqual(jobState, "FINISHED") + launcher.getJobResults(job_id, "") + try: + f = open(os.path.join(local_result_dir, "result.txt"), 'r') + text = f.read() + f.close() + self.assertEqual(text, "expected") + except IOError,ex: + self.fail("IO exception:" + str(ex)); + + ############################## + # test of yacs job type + ############################## + def test_yacs(self): + yacs_path = os.getenv("YACS_ROOT_DIR", "") + if not os.path.isdir(yacs_path): + self.skipTest("Needs YACS module to run. Please define YACS_ROOT_DIR.") + + case_test_dir = os.path.join(TestCompo.test_dir, "yacs") + os.mkdir(case_test_dir) + + #environement script + env_file = "myEnv.sh" + env_text = """export ENV_TEST_VAR="expected" +""" + f = open(os.path.join(case_test_dir, env_file), "w") + f.write(env_text) + f.close() + + # job script + script_text = """ + + + + + + + + + + + + + +""" + yacs_file = "mySchema.xml" + job_script_file = os.path.join(case_test_dir, yacs_file) + f = open(job_script_file, "w") + f.write(script_text) + f.close() + + local_result_dir = os.path.join(case_test_dir, "result_yacs_job") + job_params = salome.JobParameters() + job_params.job_name = "MyYacsJob" + job_params.job_type = "yacs_file" + job_params.job_file = job_script_file + job_params.env_file = os.path.join(case_test_dir,env_file) + #job_params.in_files = [case_test_dir] + job_params.out_files = ["result.txt"] + job_params.result_directory = local_result_dir + job_params.resource_required = salome.ResourceParameters() + job_params.resource_required.nb_proc = 1 + + job_params.work_directory = "/tmp/job_yacs" + self.suffix + + launcher = salome.naming_service.Resolve('/SalomeLauncher') + job_id = launcher.createJob(job_params) + + launcher.launchJob(job_id) + + import time + jobState = launcher.getJobState(job_id) + print "Job %d state: %s" % (job_id,jobState) + while jobState != "FINISHED" and jobState != "FAILED" : + time.sleep(5) + jobState = launcher.getJobState(job_id) + print "Job %d state: %s" % (job_id,jobState) + pass + + self.assertEqual(jobState, "FINISHED") + + # getJobResults to default directory (result_directory) + launcher.getJobResults(job_id, "") + try: + f = open(os.path.join(local_result_dir, "result.txt"), 'r') + text = f.read() + f.close() + self.assertEqual(text, "expected") + except IOError,ex: + self.fail("IO exception:" + str(ex)); + +if __name__ == '__main__': + # creat study + import salome + salome.salome_init() + unittest.main() + + # load catalogs +# mc = salome.naming_service.Resolve('/Kernel/ModulCatalog') +# ior = salome.orb.object_to_string(mc) +# import SALOMERuntime +# SALOMERuntime.RuntimeSALOME_setRuntime() +# salome_runtime = SALOMERuntime.getSALOMERuntime() +# session_catalog = salome_runtime.loadCatalog("session", ior) +# salome_runtime.addCatalog(session_catalog) + diff --git a/src/UnitTests/prepare_test.py b/src/UnitTests/prepare_test.py new file mode 100755 index 000000000..59bc0dca9 --- /dev/null +++ b/src/UnitTests/prepare_test.py @@ -0,0 +1,117 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +usage=""" +This script prepares the test environment and runs a test script: + - clean and create test directory + - create a SALOME application + - launch salome + - launch the test script within SALOME environment + - kill salome + + This script uses the following environment variables: + - ROOT_SALOME : directory which contains salome_context.cfg. + This variable is usually defined in salome_prerequisites.sh + - KERNEL_ROOT_DIR and YACS_ROOT_DIR : directories of modules installation + Those variables are usually defined in salome_modules.sh + Environment variables can be passed to the script using the -d option. +""" + +import os +import sys + +class TestEnvironment: + def setUp(self): + import shutil + shutil.rmtree("appli", ignore_errors=True) + + # create config_appli.xml in current directory + salome_path = os.getenv("ROOT_SALOME", "") + salome_context_file = os.path.join(salome_path, "salome_context.cfg") + if not os.path.isfile(salome_context_file): + print "File salome_context.cfg not found." + print "Search path:" + salome_path + print "This test needs ROOT_SALOME environment variable in order to run" + exit(1) + + config_appli_text = ''' + + + ' + + # some tests need YACS module. + yacs_path = os.getenv("YACS_ROOT_DIR", "") + if os.path.isdir(yacs_path): + cls.hasYacs = True + config_appli_text += ''' + ' + pass + config_appli_text += ''' + +''' + + f = open("config_appli.xml", 'w') + f.write(config_appli_text) + f.close() + + # create a SALOME application + appli_gen_file = os.path.join(kernel_path, + "bin","salome","appli_gen.py") + appli_dir = "appli" + os.system(appli_gen_file + " --prefix="+appli_dir+ + " --config=config_appli.xml") + + # start salome + import imp + sys.path[:0] = [os.path.join(appli_dir, "bin", "salome", "appliskel")] + self.salome_module = imp.load_source("SALOME", os.path.join(appli_dir, "salome")) + try: + self.salome_module.main(["start", "-t"]) + except SystemExit, e: + # There is an exit() call in salome.main. Just ignore it. + pass + + def run(self, script): + ret = 0 + try: + ret = self.salome_module.main(["shell", script]) + except SystemExit, e: + # return exit value + ret = e.code + return ret + + def tearDown(self): + try: + self.salome_module.main(["killall"]) + except SystemExit, e: + pass + pass + pass #class TestEnvironment + +if __name__ == '__main__': + import argparse + parser = argparse.ArgumentParser(description=usage, + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument('command', help="Test command to be run.") + parser.add_argument('-d', '--define', action='append', help="VARIABLE=VALUE") + + args = parser.parse_args() + for opt in args.define: + opts = opt.split('=', 1) + os.environ[opts[0]] = opts[1] + + envTest = TestEnvironment() + envTest.setUp() + ret = envTest.run(args.command) + envTest.tearDown() + exit(ret) + pass + -- 2.39.2