Repository: qpid-dispatch Updated Branches: refs/heads/master ce04365d5 -> 645d87e45
DISPATCH-940: Fernando Giorgetti - Config files use relative paths In addition to the original PR this commit includes test fixes: * tests shared test.pid file * test.pid file was not located well in directory hierarchy * wait_port added to prove that routers came on line * minor tweaks and class duplication to work around framework creation of config files but then starting routers with popen Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/645d87e4 Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/645d87e4 Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/645d87e4 Branch: refs/heads/master Commit: 645d87e45c64f50e22a846de7cd9a352c1a568cc Parents: ce04365 Author: Chuck Rolke <[email protected]> Authored: Fri Mar 23 17:09:07 2018 -0400 Committer: Chuck Rolke <[email protected]> Committed: Fri Mar 23 17:20:35 2018 -0400 ---------------------------------------------------------------------- router/src/main.c | 45 ++++++++- tests/CMakeLists.txt | 1 + tests/system_tests_cmdline_parsing.py | 157 +++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/645d87e4/router/src/main.c ---------------------------------------------------------------------- diff --git a/router/src/main.c b/router/src/main.c index b525dda..b6c9d53 100644 --- a/router/src/main.c +++ b/router/src/main.c @@ -26,6 +26,7 @@ #include <fcntl.h> #include <unistd.h> #include <string.h> +#include <stdlib.h> #include <getopt.h> #include <errno.h> #include "config.h" @@ -176,6 +177,46 @@ static void daemon_process(const char *config_path, const char *python_pkgdir, // umask(0); + + // + // If config path is not represented by its full path, then + // save current path before changing to / + // + char *config_path_full = NULL; + if (strncmp("/", config_path, 1)) { + char *cur_path = NULL; + size_t path_size = 256; + int getcwd_error = 0; + cur_path = (char *) calloc(path_size, sizeof(char)); + + while ( getcwd(cur_path, path_size) == NULL ) { + free(cur_path); + if ( errno != ERANGE ) { + // If unable to get current directory + getcwd_error = 1; + break; + } + // If current path does not fit, allocate more memory + path_size += 256; + cur_path = (char *) calloc(path_size, sizeof(char)); + } + + // Populating fully qualified config file name + if (!getcwd_error) { + size_t cpf_len = path_size + strlen(config_path) + 1; + config_path_full = calloc(cpf_len, sizeof(char)); + snprintf(config_path_full, cpf_len, "%s%s%s", + cur_path, + !strcmp("/", cur_path)? "":"/", + config_path); + } + + // Releasing temporary path variable + memset(cur_path, 0, path_size * sizeof(char)); + free(cur_path); + + } + // // Set the current directory to "/" to avoid blocking // mount points @@ -203,7 +244,9 @@ static void daemon_process(const char *config_path, const char *python_pkgdir, //if (setgid(pwd->pw_gid) < 0) fail(pipefd[1], "Can't set group ID for user %s, errno=%d", user, errno); } - main_process(config_path, python_pkgdir, pipefd[1]); + main_process((config_path_full ? config_path_full : config_path), python_pkgdir, pipefd[1]); + + free(config_path_full); } else // // Exit first child http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/645d87e4/tests/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b2f0f2e..939b51f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -108,6 +108,7 @@ foreach(py_test_module system_tests_topology_addition system_tests_disallow_link_resumable_link_route system_tests_exchange_bindings + system_tests_cmdline_parsing ${SYSTEM_TESTS_HTTP} ) http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/645d87e4/tests/system_tests_cmdline_parsing.py ---------------------------------------------------------------------- diff --git a/tests/system_tests_cmdline_parsing.py b/tests/system_tests_cmdline_parsing.py new file mode 100644 index 0000000..eca8e0c --- /dev/null +++ b/tests/system_tests_cmdline_parsing.py @@ -0,0 +1,157 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +""" +This is a unit test class used to validate how qdrouterd +behaves with different command line arguments combinations, +in order to ensure it won't break, causing bad experiences +to the users. +""" + +import os +import signal +from subprocess import PIPE, STDOUT +import unittest2 as unittest +from system_test import TestCase, Qdrouterd, main_module, Process, wait_port + +class CommandLineTest(TestCase): + """ + System tests for command line arguments parsing + """ + testport = 0 + testname = "" + + @classmethod + def setUpClass(cls): + """Uses a default config for testing""" + + super(CommandLineTest, cls).setUpClass() + cls.name = "test-router-1" + CommandLineTest.testname = cls.name + CommandLineTest.testport = cls.tester.get_port() + cls.config = Qdrouterd.Config([ + ('router', {'mode': 'standalone', 'id': CommandLineTest.name}), + ('listener', {'port': CommandLineTest.testport}), + ('log',{'module':'DEFAULT', 'enable':'trace+', 'source': 'true', 'output': os.getcwd()+"/"+CommandLineTest.name+'.log'}) + ]) + + def run_qdrouterd_as_daemon(self, config_file_name, + pid_file_name): + """ + Runs qdrouterd as a daemon, using the provided config_file_name + in order to ensure router is able to load it, be it using a + full or relative path. + + :param config_file_name: The configuration file name to be written + :param pid_file_name: PID file name (must be full path) + :return: + """ + pipe = self.popen( + ['qdrouterd', '-d', '-c', + self.config.write(config_file_name), '-P', pid_file_name], + stdout=PIPE, stderr=STDOUT, expect=Process.EXIT_OK) + out = pipe.communicate()[0] + wait_port(CommandLineTest.testport) + + try: + pipe.teardown() + # kill qdrouterd running as a daemon + with open(pid_file_name, 'r') as pidfile: + for line in pidfile: + os.kill(int(line), signal.SIGTERM) + pidfile.close() + except OSError as ex: + raise Exception("%s\n%s" % (ex, out)) + + + def test_01_config_relative_path(self): + """ + Starts qdrouterd as daemon, enforcing a config file name with + relative path. + """ + + try: + self.run_qdrouterd_as_daemon("test-router", os.getcwd()+'/test.pid') + except OSError as ex: + self.fail(ex) + +class CommandLineTest2(TestCase): + """ + System tests for command line arguments parsing + """ + testport = 0 + testname = "" + + @classmethod + def setUpClass(cls): + """Uses a default config for testing""" + + super(CommandLineTest2, cls).setUpClass() + cls.name = "test-router-2" + CommandLineTest2.testname = cls.name + CommandLineTest2.testport = cls.tester.get_port() + cls.config = Qdrouterd.Config([ + ('router', {'mode': 'standalone', 'id': CommandLineTest2.testname}), + ('listener', {'port': CommandLineTest2.testport}), + ('log',{'module':'DEFAULT', 'enable':'trace+', 'source': 'true', 'output': os.getcwd()+"/"+CommandLineTest2.name+'.log'}) + ]) + + def run_qdrouterd_as_daemon(self, config_file_name, pid_file_name): + """ + Runs qdrouterd as a daemon, using the provided config_file_name + in order to ensure router is able to load it, be it using a + full or relative path. + + :param config_file_name: The configuration file name to be written + :param pid_file_name: PID file name (must be full path) + :return: + """ + pipe = self.popen( + ['qdrouterd', '-d', '-c', + self.config.write(config_file_name), '-P', pid_file_name], + stdout=PIPE, stderr=STDOUT, expect=Process.EXIT_OK) + out = pipe.communicate()[0] + wait_port(CommandLineTest2.testport) + + try: + pipe.teardown() + # kill qdrouterd running as a daemon + with open(pid_file_name, 'r') as pidfile: + for line in pidfile: + os.kill(int(line), signal.SIGTERM) + pidfile.close() + except OSError as ex: + raise Exception("%s\n%s" % (ex, out)) + + + def test_02_config_full_path(self): + """ + Starts qdrouterd as daemon, enforcing a config file name with + full path. + """ + + try: + self.run_qdrouterd_as_daemon(os.getcwd() + "/test-router-2.conf", + pid_file_name=os.getcwd()+'/test.pid') + except OSError as ex: + self.fail(ex) + + +if __name__ == '__main__': + unittest.main(main_module()) --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
