From f1c57aaebdf0c680d5b85f6198d355aea95dc5d9 Mon Sep 17 00:00:00 2001 From: Lukasz Marek Date: Fri, 2 Aug 2013 15:51:11 +0200 Subject: [PATCH] Fix RUNNER_CHILD_TEST framework. Fixes: * Add support for Ignore macro in child process. Now parent process print result in corrent way. * Fix SIGPIPE problem when test process want to use function write with stdout or stderr in RUNNER_CHILD_TEST. (Problem occures only when environment value DPL_USE_OLD_STYLE_LOGS=1 was defined). [Issue#] N/A [Problem] Macro RUNNER_IGNORE_MSG was not allowed in child test process. Call write(stdout, ...) in RUNNER_CHILD_TEST cause SIGPIPE. [Cause] Lack of support exception "TestRunner::Ignored" Lack of stdout and stderr descriptor in child process. [Solution] Add support for Exception "TestRunner::Ignored" in RUNNER_CHILD_TEST Change-Id: I7f69972ed6d2f6fea16584058c29acd9c8f0a27a --- modules/test/src/test_runner_child.cpp | 57 ++++++++++++++++++-------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/modules/test/src/test_runner_child.cpp b/modules/test/src/test_runner_child.cpp index 223a47a..db1ba29 100644 --- a/modules/test/src/test_runner_child.cpp +++ b/modules/test/src/test_runner_child.cpp @@ -38,14 +38,42 @@ #include #include #include +#include #include #include +#include #include namespace { const int PIPE_CLOSED = -1; + +const int CHILD_TEST_FAIL = 0; +const int CHILD_TEST_PASS = 1; +const int CHILD_TEST_IGNORED = 2; + +int closeOutput() { + int devnull; + int retcode = -1; + if (-1 == (devnull = TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY)))) + return -1; + + // replace stdout with /dev/null + if (-1 == TEMP_FAILURE_RETRY(dup2(devnull, STDOUT_FILENO))) + goto end; + + // replace stderr with /dev/null + if (-1 == TEMP_FAILURE_RETRY(dup2(devnull, STDERR_FILENO))) + goto end; + + retcode = 0; + +end: + close(devnull); + return retcode; } +} // namespace anonymous + namespace DPL { namespace Test { class PipeWrapper : DPL::Noncopyable @@ -269,11 +297,10 @@ void RunChildProc(TestRunner::TestCase procChild) throw TestRunner::TestFailed("Reading pipe error"); } - if (code == 0) { + if (code == CHILD_TEST_FAIL) { throw TestRunner::TestFailed(message); - } - if (code == 2) { - throw TestRunner::TestFailed("Ignored"); + } else if (code == CHILD_TEST_IGNORED) { + throw TestRunner::Ignored(message); } } else { // child code @@ -281,35 +308,33 @@ void RunChildProc(TestRunner::TestCase procChild) // End Runner after current test TestRunnerSingleton::Instance().Terminate(); - int code = 1; + int code = CHILD_TEST_PASS; std::string msg; bool allowLogs = TestRunnerSingleton::Instance().GetAllowChildLogs(); - close(0); // stdin + close(STDIN_FILENO); if (!allowLogs) { - close(1); // stdout - close(2); // stderr + closeOutput(); // if fails nothing we can do } pipe.setUsage(PipeWrapper::WRITEONLY); try { procChild(); - } catch (DPL::Test::TestRunner::TestFailed &e) { + } catch (const DPL::Test::TestRunner::TestFailed &e) { msg = e.GetMessage(); - code = 0; - } catch (DPL::Test::TestRunner::Ignored &e) { + code = CHILD_TEST_FAIL; + } catch (const DPL::Test::TestRunner::Ignored &e) { msg = e.GetMessage(); - code = 2; - } catch (...) { // Pokemon Catch... cache them all... + code = CHILD_TEST_IGNORED; + } catch (...) { // catch all exception generated by "user" code msg = "unhandled exeception"; - code = 0; + code = CHILD_TEST_FAIL; } if (allowLogs) { - close(1); // stdout - close(2); // stderr + closeOutput(); } pipe.send(code, msg); -- 2.34.1