[DPL] ProcessPipe
authorTomasz Iwanek <t.iwanek@samsung.com>
Thu, 11 Jul 2013 15:29:52 +0000 (17:29 +0200)
committerGerrit Code Review <gerrit@gerrit.vlan144.tizendev.org>
Thu, 1 Aug 2013 09:34:15 +0000 (09:34 +0000)
[Issue#]       LINUXWRT-639
[Feature]      Utility to spawn subprocess o read and write bytes through named pipes
[Cause]        N/A
[Solution]     This will be used in tests. Whats more this was problem in wrt-extra for some tests.
[Verification] Build repository with tests and with WITH_CHILD ON. Run tests: wrt-commons-tests-test --output=text --regexp='ProcessPipe_' #all should pass

Change-Id: I92915b53b9542cd2e523e42669e37ebd050eaf81

modules/test/config.cmake
modules/test/include/dpl/test/process_pipe.h [new file with mode: 0644]
modules/test/src/process_pipe.cpp [new file with mode: 0644]
tests/test/CMakeLists.txt
tests/test/test_process_pipe.cpp [new file with mode: 0644]

index d3485cf..d08366c 100644 (file)
@@ -23,6 +23,7 @@ SET(DPL_TEST_ENGINE_SOURCES
     ${PROJECT_SOURCE_DIR}/modules/test/src/test_results_collector.cpp
     ${PROJECT_SOURCE_DIR}/modules/test/src/test_runner.cpp
     ${PROJECT_SOURCE_DIR}/modules/test/src/test_runner_child.cpp
+    ${PROJECT_SOURCE_DIR}/modules/test/src/process_pipe.cpp
     PARENT_SCOPE
 )
 
@@ -31,6 +32,7 @@ SET(DPL_TEST_ENGINE_HEADERS
     ${PROJECT_SOURCE_DIR}/modules/test/include/dpl/test/test_results_collector.h
     ${PROJECT_SOURCE_DIR}/modules/test/include/dpl/test/test_runner.h
     ${PROJECT_SOURCE_DIR}/modules/test/include/dpl/test/test_runner_child.h
+    ${PROJECT_SOURCE_DIR}/modules/test/include/dpl/test/process_pipe.h
     PARENT_SCOPE
 )
 
diff --git a/modules/test/include/dpl/test/process_pipe.h b/modules/test/include/dpl/test/process_pipe.h
new file mode 100644 (file)
index 0000000..52ab7e7
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed 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.
+ */
+/*
+ * @file        process_pipe.h
+ * @author      Tomasz Iwanek (t.iwanek@samsung.com)
+ * @version     1.0
+ * @brief       This file is the implementation pipe from process
+ */
+#ifndef PROCESS_PIPE_H
+#define PROCESS_PIPE_H
+
+#include <dpl/file_input.h>
+#include <dpl/exception.h>
+
+#include <cstdio>
+
+namespace DPL {
+
+class ProcessPipe : public FileInput
+{
+public:
+    class Exception
+    {
+    public:
+        DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+        DECLARE_EXCEPTION_TYPE(Base, DoubleOpen)
+    };
+
+    enum class PipeErrorPolicy
+    {
+        NONE,
+        OFF,
+        PIPE
+    };
+
+    explicit ProcessPipe(PipeErrorPolicy err = PipeErrorPolicy::NONE);
+    virtual ~ProcessPipe();
+
+    void Open(const std::string &command);
+    void Close();
+
+private:
+    FILE * m_file;
+    PipeErrorPolicy m_errPolicy;
+};
+
+}
+
+#endif // PROCESS_PIPE_H
diff --git a/modules/test/src/process_pipe.cpp b/modules/test/src/process_pipe.cpp
new file mode 100644 (file)
index 0000000..68c910f
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed 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.
+ */
+/*
+ * @file        process_pipe.cpp
+ * @author      Tomasz Iwanek (t.iwanek@samsung.com)
+ * @version     1.0
+ * @brief       This file is the implementation pipe from process
+ */
+
+#include<dpl/test/process_pipe.h>
+#include<dpl/log/log.h>
+
+namespace DPL {
+
+ProcessPipe::ProcessPipe(PipeErrorPolicy err) : m_file(NULL), m_errPolicy(err)
+{
+}
+
+ProcessPipe::~ProcessPipe()
+{
+}
+
+void ProcessPipe::Open(const std::string & command)
+{
+    if(m_file != NULL)
+    {
+        ThrowMsg(Exception::DoubleOpen, "Trying to open pipe second time. Close it first");
+    }
+
+    std::string stdErrRedirection;
+    switch(m_errPolicy)
+    {
+        case PipeErrorPolicy::NONE:                                      break;
+        case PipeErrorPolicy::OFF:   stdErrRedirection = " 2>/dev/null"; break;
+        case PipeErrorPolicy::PIPE:  stdErrRedirection = " 2>&1";        break;
+        default:                                                         break;
+    }
+
+    std::string fcommand = command + stdErrRedirection;
+    FILE * file = popen(fcommand.c_str(), "r");
+
+    // Throw an exception if an error occurred
+    if (file == NULL) {
+        ThrowMsg(FileInput::Exception::OpenFailed, fcommand);
+    }
+
+    // Save new descriptor
+    m_file = file;
+    m_fd = fileno(m_file);
+
+    LogPedantic("Opened pipe: " << fcommand);
+}
+
+void ProcessPipe::Close()
+{
+    if (m_fd == -1) {
+        return;
+    }
+
+    if (pclose(m_file) == -1) {
+        Throw(FileInput::Exception::CloseFailed);
+    }
+
+    m_fd = -1;
+    m_file = NULL;
+
+    LogPedantic("Closed pipe");
+}
+
+}
index 1c0bf55..48fb045 100644 (file)
 # @brief
 #
 
-SET(TARGET_NAME "wrt-commons-tests-test-runner-child")
+SET(TARGET_NAME "wrt-commons-tests-test")
 
 # Set DPL tests sources
 SET(DPL_TESTS_UTIL_SOURCES
     ${TESTS_DIR}/test/main.cpp
     ${TESTS_DIR}/test/runner_child.cpp
+    ${TESTS_DIR}/test/test_process_pipe.cpp
 )
 
 #WRT_TEST_ADD_INTERNAL_DEPENDENCIES(${TARGET_NAME} ${TARGET_DPL_UTILS_EFL})
diff --git a/tests/test/test_process_pipe.cpp b/tests/test/test_process_pipe.cpp
new file mode 100644 (file)
index 0000000..ffc8a8d
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed 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.
+ */
+/*
+ * @file        test_process_pipe.cpp
+ * @author      Tomasz Iwanek (t.iwanek@samsung.com)
+ * @version     1.0
+ * @brief       This file is the implementation file of ProcessPipe tests
+ */
+
+#include <dpl/test/test_runner.h>
+#include <dpl/test/process_pipe.h>
+#include <dpl/binary_queue.h>
+#include <dpl/log/log.h>
+
+#include <cstring>
+
+using namespace DPL;
+
+RUNNER_TEST_GROUP_INIT(DPL)
+
+namespace {
+void readAll(ProcessPipe & npp, BinaryQueue & result)
+{
+    do
+    {
+        BinaryQueueAutoPtr dataptr = npp.Read(4096);
+
+        RUNNER_ASSERT_MSG(dataptr.get() != NULL, "Cannot read from pipe subprocess");
+
+        LogDebug("Size: " << dataptr->Size());
+
+        if(dataptr->Empty()) break;
+        result.AppendMoveFrom(*dataptr);
+    }
+    while(true);
+}
+}
+
+RUNNER_TEST(ProcessPipe_echo)
+{
+    ProcessPipe npp;
+    npp.Open("echo -e \"Test echo text\\nAnd new line\"");
+    BinaryQueue result;
+    readAll(npp, result);
+    npp.Close();
+
+    char buffer[100] = "";
+    result.FlattenConsume(buffer, 99);
+
+    RUNNER_ASSERT_MSG(strcmp(buffer, "Test echo text\nAnd new line\n") == 0, "Echoed text in not equal");
+}
+
+RUNNER_TEST(ProcessPipe_double_open)
+{
+    ProcessPipe npp;
+    npp.Open("echo  \"Test \"");
+    Try
+    {
+        npp.Open("echo \"Test\"");
+    }
+    Catch(DPL::ProcessPipe::Exception::DoubleOpen)
+    {
+        npp.Close();
+        return;
+    }
+    npp.Close();
+    RUNNER_ASSERT_MSG(false, "DoubleOpen not thrown");
+}
+
+RUNNER_TEST(ProcessPipe_double_close)
+{
+    ProcessPipe npp;
+    npp.Open("echo  \"Test invalid\"");
+    npp.Close();
+    Try
+    {
+        npp.Close();
+    }
+    Catch(DPL::Exception)
+    {
+        RUNNER_ASSERT_MSG(false, "Second Close throws exception");
+    }
+}
+
+RUNNER_TEST(ProcessPipe_pipeerror_off)
+{
+    ProcessPipe npp(ProcessPipe::PipeErrorPolicy::OFF);
+    npp.Open("ls /nonexistingdirectory");
+    BinaryQueue result;
+    readAll(npp, result); //TODO: fix this test
+    npp.Close();
+}
+
+RUNNER_TEST(ProcessPipe_pipeerror_pipe)
+{
+    //ls output dependent...
+    ProcessPipe npp(ProcessPipe::PipeErrorPolicy::PIPE);
+    npp.Open("ls /nonexistingdirectory");
+    BinaryQueue result;
+    readAll(npp, result);
+    npp.Close();
+    char buffer[100] = "";
+    result.FlattenConsume(buffer, 99);
+
+    RUNNER_ASSERT_MSG(strcmp(buffer, "ls: cannot access /nonexistingdirectory: No such file or directory\n") == 0, "Ls error text in not equal");
+}