Fix RUNNER_CHILD_TEST framework.
authorLukasz Marek <l.marek@samsung.com>
Fri, 2 Aug 2013 13:51:11 +0000 (15:51 +0200)
committerGerrit Code Review <gerrit@gerrit.vlan144.tizendev.org>
Tue, 20 Aug 2013 05:25:35 +0000 (05:25 +0000)
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

index 223a47a..db1ba29 100644 (file)
 #include <ctime>
 #include <unistd.h>
 #include <poll.h>
+#include <fcntl.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <sys/stat.h>
 #include <dpl/utils/wrt_global_settings.h>
 
 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);