[Release] wrt-commons_0.2.151
authorsung-su.kim <sung-su.kim@samsung.com>
Wed, 4 Sep 2013 06:57:58 +0000 (15:57 +0900)
committersung-su.kim <sung-su.kim@samsung.com>
Wed, 4 Sep 2013 06:57:58 +0000 (15:57 +0900)
Change-Id: Ib018f8e7921446fb4430f5f60eb189ef55ffef79

16 files changed:
modules/core/config.cmake
modules/core/include/dpl/mutable_task_list.h [new file with mode: 0644]
modules/core/src/mutable_task_list.cpp [new file with mode: 0644]
modules/test/config.cmake
modules/test/include/dpl/test/test_runner_child.h
modules/test/include/dpl/test/test_runner_multiprocess.h [new file with mode: 0644]
modules/test/src/test_runner_child.cpp
modules/test/src/test_runner_multiprocess.cpp [new file with mode: 0644]
modules/utils/include/dpl/utils/path.h
modules/utils/src/path.cpp
modules/widget_dao/include/dpl/wrt-dao-ro/global_config.h
packaging/wrt-commons.spec
tests/test/CMakeLists.txt
tests/test/runner_multiprocess.cpp [new file with mode: 0644]
tests/test/test_process_pipe.cpp
tests/utils/path_tests.cpp

index 35bbbf3..33f25ea 100644 (file)
@@ -38,6 +38,7 @@ SET(DPL_CORE_SOURCES
     ${PROJECT_SOURCE_DIR}/modules/core/src/file_input.cpp
     ${PROJECT_SOURCE_DIR}/modules/core/src/file_output.cpp
     ${PROJECT_SOURCE_DIR}/modules/core/src/lexical_cast.cpp
+    ${PROJECT_SOURCE_DIR}/modules/core/src/mutable_task_list.cpp
     ${PROJECT_SOURCE_DIR}/modules/core/src/mutex.cpp
     ${PROJECT_SOURCE_DIR}/modules/core/src/named_base_pipe.cpp
     ${PROJECT_SOURCE_DIR}/modules/core/src/named_output_pipe.cpp
@@ -98,6 +99,7 @@ SET(DPL_CORE_HEADERS
     ${PROJECT_SOURCE_DIR}/modules/core/include/dpl/foreach.h
     ${PROJECT_SOURCE_DIR}/modules/core/include/dpl/generic_event.h
     ${PROJECT_SOURCE_DIR}/modules/core/include/dpl/lexical_cast.h
+    ${PROJECT_SOURCE_DIR}/modules/core/include/dpl/mutable_task_list.h
     ${PROJECT_SOURCE_DIR}/modules/core/include/dpl/mutex.h
     ${PROJECT_SOURCE_DIR}/modules/core/include/dpl/named_base_pipe.h
     ${PROJECT_SOURCE_DIR}/modules/core/include/dpl/named_input_pipe.h
diff --git a/modules/core/include/dpl/mutable_task_list.h b/modules/core/include/dpl/mutable_task_list.h
new file mode 100644 (file)
index 0000000..9facbd3
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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    mutable_task_list.h
+ * @author  Tomasz Iwanek (t.iwanek@samsung.com)
+ * @version 1.0
+ * @brief   Header file for task list
+ */
+#ifndef DPL_MUTABLE_TASK_LIST_H
+#define DPL_MUTABLE_TASK_LIST_H
+
+#include <dpl/task.h>
+#include <list>
+
+namespace DPL {
+class MutableTaskList :
+    public Task
+{
+    private:
+        typedef std::list<Task *> Tasks;
+
+        Tasks m_tasks;
+        Tasks::iterator m_currentTask;
+
+        bool m_running;
+
+    protected:
+        void AddTask(Task *task);
+
+    public:
+        MutableTaskList();
+        virtual ~MutableTaskList();
+
+        bool NextStep();
+        bool Abort();
+        size_t GetStepCount() const;
+};
+} // namespace DPL
+
+#endif // DPL_MUTABLE_TASK_LIST_H
diff --git a/modules/core/src/mutable_task_list.cpp b/modules/core/src/mutable_task_list.cpp
new file mode 100644 (file)
index 0000000..67576b8
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * 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    task_list.cpp
+ * @author  Tomasz Iwanek (t.iwanek@samsung.com)
+ * @version 1.0
+ * @brief   Implementation file for task list
+ */
+#include <stddef.h>
+#include <dpl/mutable_task_list.h>
+#include <dpl/assert.h>
+
+namespace DPL {
+MutableTaskList::MutableTaskList() :
+    m_running(false)
+{
+    m_currentTask = m_tasks.end();
+}
+
+MutableTaskList::~MutableTaskList()
+{
+    for (Tasks::iterator i = m_tasks.begin(); i != m_tasks.end(); ++i) {
+        delete *i;
+    }
+}
+
+void MutableTaskList::AddTask(Task *task)
+{
+    if(m_tasks.empty())
+    {
+        m_tasks.push_back(task);
+        m_currentTask = m_tasks.begin();
+    }
+    else
+    {
+        m_tasks.push_back(task);
+    }
+}
+
+bool MutableTaskList::NextStep()
+{
+    m_running = true;
+
+    Assert(
+        m_currentTask != m_tasks.end() &&
+        "Task list is empty or all tasks done");
+
+    bool result = (*m_currentTask)->NextStep();
+
+    if (result) {
+        return true;
+    }
+
+    return ++m_currentTask != m_tasks.end();
+}
+
+bool MutableTaskList::Abort()
+{
+    m_tasks.erase(m_currentTask, m_tasks.end());
+    m_tasks.reverse();
+    for (Tasks::iterator i = m_tasks.begin(); i != m_tasks.end();) {
+        //If given task does not have any "abortSteps", remove it from the list
+        if (!(*i)->Abort()) {
+            delete *i;
+            i = m_tasks.erase(i);
+            continue;
+        }
+        ++i;
+    }
+
+    if (m_tasks.empty()) {
+        return false;
+    }
+
+    m_currentTask = m_tasks.begin();
+
+    return true;
+}
+
+size_t MutableTaskList::GetStepCount() const
+{
+    size_t count = 0;
+
+    for (Tasks::const_iterator i = m_tasks.begin(); i != m_tasks.end(); ++i) {
+        count += (*i)->GetStepCount();
+    }
+
+    return count;
+}
+
+} // namespace DPL
index d08366c..7938eaf 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/test_runner_multiprocess.cpp
     ${PROJECT_SOURCE_DIR}/modules/test/src/process_pipe.cpp
     PARENT_SCOPE
 )
@@ -32,6 +33,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/test_runner_multiprocess.h
     ${PROJECT_SOURCE_DIR}/modules/test/include/dpl/test/process_pipe.h
     PARENT_SCOPE
 )
index b20c371..1da0f1b 100644 (file)
 
 namespace DPL {
 namespace Test {
+
+class PipeWrapper : DPL::Noncopyable
+{
+  public:
+    enum Usage {
+        READONLY,
+        WRITEONLY
+    };
+
+    enum Status {
+        SUCCESS,
+        TIMEOUT,
+        ERROR
+    };
+
+    PipeWrapper();
+
+    bool isReady();
+
+    void setUsage(Usage usage);
+
+    virtual ~PipeWrapper();
+
+    Status send(int code, std::string &message);
+
+    Status receive(int &code, std::string &data, time_t deadline);
+
+    void closeAll();
+
+  protected:
+
+    std::string toBinaryString(int data);
+
+    void closeHelp(int desc);
+
+    Status writeHelp(const void *buffer, int size);
+
+    Status readHelp(void *buf, int size, time_t deadline);
+
+    static const int PIPE_CLOSED = -1;
+
+    int m_pipefd[2];
+};
+
 void RunChildProc(TestRunner::TestCase procChild);
 } // namespace Test
 } // namespace DPL
diff --git a/modules/test/include/dpl/test/test_runner_multiprocess.h b/modules/test/include/dpl/test/test_runner_multiprocess.h
new file mode 100644 (file)
index 0000000..279b5ef
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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_runner_multiprocess.h
+ * @author      Marcin Niesluchowski (m.niesluchow@samsung.com)
+ * @version     1.0
+ * @brief       This file is the header file of multiprocess test runner
+ */
+#ifndef DPL_TEST_RUNNER_MULTIPROCESS_H
+#define DPL_TEST_RUNNER_MULTIPROCESS_H
+
+#include <dpl/test/test_runner_child.h>
+
+namespace DPL {
+namespace Test {
+
+class SimplePipeWrapper :
+        public PipeWrapper
+{
+  public:
+    SimplePipeWrapper();
+
+    virtual ~SimplePipeWrapper();
+
+    Status send(std::string &message);
+    Status receive(std::string &data, bool &empty, time_t deadline);
+};
+
+void RunMultiProc(TestRunner::TestCase procMulti);
+} // namespace Test
+} // namespace DPL
+
+#define RUNNER_MULTIPROCESS_TEST(Proc)                                               \
+    void Proc();                                                                     \
+    void Proc##Multi();                                                              \
+    static int Static##Proc##Init()                                                  \
+    {                                                                                \
+        DPL::Test::TestRunnerSingleton::Instance().RegisterTest(#Proc, &Proc);       \
+        return 0;                                                                    \
+    }                                                                                \
+    const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init();               \
+    void Proc(){                                                                     \
+        DPL::Test::RunMultiProc(&Proc##Multi);                                       \
+    }                                                                                \
+    void Proc##Multi()
+
+#endif // DPL_TEST_RUNNER_MULTIPROCESS_H
index db1ba29..8e793e8 100644 (file)
@@ -45,8 +45,6 @@
 #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;
@@ -76,188 +74,172 @@ end:
 
 namespace DPL {
 namespace Test {
-class PipeWrapper : DPL::Noncopyable
+
+PipeWrapper::PipeWrapper()
 {
-  public:
-    enum Usage {
-        READONLY,
-        WRITEONLY
-    };
-
-    enum Status {
-        SUCCESS,
-        TIMEOUT,
-        ERROR
-    };
-
-    PipeWrapper()
-    {
-        if (-1 == pipe(m_pipefd)) {
-            m_pipefd[0] = PIPE_CLOSED;
-            m_pipefd[1] = PIPE_CLOSED;
-        }
+    if (-1 == pipe(m_pipefd)) {
+        m_pipefd[0] = PIPE_CLOSED;
+        m_pipefd[1] = PIPE_CLOSED;
     }
+}
 
-    bool isReady()
-    {
-        return m_pipefd[0] != PIPE_CLOSED || m_pipefd[1] != PIPE_CLOSED;
-    }
+PipeWrapper::~PipeWrapper()
+{
+    closeHelp(0);
+    closeHelp(1);
+}
 
-    void setUsage(Usage usage)
-    {
-        if (usage == READONLY) {
-            closeHelp(1);
-        }
-        if (usage == WRITEONLY) {
-            closeHelp(0);
-        }
+bool PipeWrapper::isReady()
+{
+    return m_pipefd[0] != PIPE_CLOSED || m_pipefd[1] != PIPE_CLOSED;
+}
+
+void PipeWrapper::setUsage(Usage usage)
+{
+    if (usage == READONLY) {
+        closeHelp(1);
     }
-    ~PipeWrapper()
-    {
+    if (usage == WRITEONLY) {
         closeHelp(0);
-        closeHelp(1);
     }
+}
 
-    Status send(int code, std::string &message)
-    {
-        if (m_pipefd[1] == PIPE_CLOSED) {
-            return ERROR;
-        }
+PipeWrapper::Status PipeWrapper::send(int code, std::string &message)
+{
+    if (m_pipefd[1] == PIPE_CLOSED) {
+        return ERROR;
+    }
 
-        std::ostringstream output;
-        output << toBinaryString(code);
-        output << toBinaryString(static_cast<int>(message.size()));
-        output << message;
+    std::ostringstream output;
+    output << toBinaryString(code);
+    output << toBinaryString(static_cast<int>(message.size()));
+    output << message;
 
-        std::string binary = output.str();
-        int size = binary.size();
+    std::string binary = output.str();
+    int size = binary.size();
 
-        if ((writeHelp(&size,
-                       sizeof(int)) == ERROR) ||
-            (writeHelp(binary.c_str(), size) == ERROR))
-        {
-            return ERROR;
-        }
-        return SUCCESS;
+    if ((writeHelp(&size,
+                   sizeof(int)) == ERROR) ||
+        (writeHelp(binary.c_str(), size) == ERROR))
+    {
+        return ERROR;
     }
+    return SUCCESS;
+}
 
-    Status receive(int &code, std::string &data, time_t deadline)
-    {
-        if (m_pipefd[0] == PIPE_CLOSED) {
-            return ERROR;
-        }
+PipeWrapper::Status PipeWrapper::receive(int &code, std::string &data, time_t deadline)
+{
+    if (m_pipefd[0] == PIPE_CLOSED) {
+        return ERROR;
+    }
 
-        int size;
-        Status ret;
+    int size;
+    Status ret;
 
-        if ((ret = readHelp(&size, sizeof(int), deadline)) != SUCCESS) {
-            return ret;
-        }
+    if ((ret = readHelp(&size, sizeof(int), deadline)) != SUCCESS) {
+        return ret;
+    }
 
-        std::vector<char> buffer;
-        buffer.resize(size);
+    std::vector<char> buffer;
+    buffer.resize(size);
 
-        if ((ret = readHelp(&buffer[0], size, deadline)) != SUCCESS) {
-            return ret;
-        }
+    if ((ret = readHelp(&buffer[0], size, deadline)) != SUCCESS) {
+        return ret;
+    }
 
-        try {
-            DPL::BinaryQueue queue;
-            queue.AppendCopy(&buffer[0], size);
+    try {
+        DPL::BinaryQueue queue;
+        queue.AppendCopy(&buffer[0], size);
 
-            queue.FlattenConsume(&code, sizeof(int));
-            queue.FlattenConsume(&size, sizeof(int));
+        queue.FlattenConsume(&code, sizeof(int));
+        queue.FlattenConsume(&size, sizeof(int));
 
-            buffer.resize(size);
+        buffer.resize(size);
 
-            queue.FlattenConsume(&buffer[0], size);
-            data.assign(buffer.begin(), buffer.end());
-        } catch (DPL::BinaryQueue::Exception::Base &e) {
-            return ERROR;
-        }
-        return SUCCESS;
+        queue.FlattenConsume(&buffer[0], size);
+        data.assign(buffer.begin(), buffer.end());
+    } catch (DPL::BinaryQueue::Exception::Base &e) {
+        return ERROR;
     }
+    return SUCCESS;
+}
 
-    void closeAll()
-    {
-        closeHelp(0);
-        closeHelp(1);
-    }
+void PipeWrapper::closeAll()
+{
+    closeHelp(0);
+    closeHelp(1);
+}
 
-  private:
-    std::string toBinaryString(int data)
-    {
-        char buffer[sizeof(int)];
-        memcpy(buffer, &data, sizeof(int));
-        return std::string(buffer, buffer + sizeof(int));
-    }
+std::string PipeWrapper::toBinaryString(int data)
+{
+    char buffer[sizeof(int)];
+    memcpy(buffer, &data, sizeof(int));
+    return std::string(buffer, buffer + sizeof(int));
+}
 
-    void closeHelp(int desc)
-    {
-        if (m_pipefd[desc] != PIPE_CLOSED) {
-            TEMP_FAILURE_RETRY(close(m_pipefd[desc]));
-            m_pipefd[desc] = PIPE_CLOSED;
-        }
+void PipeWrapper::closeHelp(int desc)
+{
+    if (m_pipefd[desc] != PIPE_CLOSED) {
+        TEMP_FAILURE_RETRY(close(m_pipefd[desc]));
+        m_pipefd[desc] = PIPE_CLOSED;
     }
+}
 
-    Status writeHelp(const void *buffer, int size)
-    {
-        int ready = 0;
-        const char *p = static_cast<const char *>(buffer);
-        while (ready != size) {
-            int ret = write(m_pipefd[1], &p[ready], size - ready);
-
-            if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
-                continue;
-            }
+PipeWrapper::Status PipeWrapper::writeHelp(const void *buffer, int size)
+{
+    int ready = 0;
+    const char *p = static_cast<const char *>(buffer);
+    while (ready != size) {
+        int ret = write(m_pipefd[1], &p[ready], size - ready);
 
-            if (ret == -1) {
-                closeHelp(1);
-                return ERROR;
-            }
+        if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
+            continue;
+        }
 
-            ready += ret;
+        if (ret == -1) {
+            closeHelp(1);
+            return ERROR;
         }
-        return SUCCESS;
-    }
 
-    Status readHelp(void *buf, int size, time_t deadline)
-    {
-        int ready = 0;
-        char *buffer = static_cast<char*>(buf);
-        while (ready != size) {
-            time_t wait = deadline - time(0);
-            wait = wait < 1 ? 1 : wait;
-            pollfd fds = { m_pipefd[0], POLLIN, 0 };
+        ready += ret;
+    }
+    return SUCCESS;
+}
 
-            int pollReturn = poll(&fds, 1, wait * 1000);
+PipeWrapper::Status PipeWrapper::readHelp(void *buf, int size, time_t deadline)
+{
+    int ready = 0;
+    char *buffer = static_cast<char*>(buf);
+    while (ready != size) {
+        time_t wait = deadline - time(0);
+        wait = wait < 1 ? 1 : wait;
+        pollfd fds = { m_pipefd[0], POLLIN, 0 };
 
-            if (pollReturn == 0) {
-                return TIMEOUT; // Timeout
-            }
+        int pollReturn = poll(&fds, 1, wait * 1000);
 
-            if (pollReturn < -1) {
-                return ERROR;
-            }
+        if (pollReturn == 0) {
+            return TIMEOUT; // Timeout
+        }
 
-            int ret = read(m_pipefd[0], &buffer[ready], size - ready);
+        if (pollReturn < -1) {
+            return ERROR;
+        }
 
-            if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
-                continue;
-            }
+        int ret = read(m_pipefd[0], &buffer[ready], size - ready);
 
-            if (ret == -1 || ret == 0) {
-                closeHelp(0);
-                return ERROR;
-            }
+        if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
+            continue;
+        }
 
-            ready += ret;
+        if (ret == -1 || ret == 0) {
+            closeHelp(0);
+            return ERROR;
         }
-        return SUCCESS;
-    }
 
-    int m_pipefd[2];
-};
+        ready += ret;
+    }
+    return SUCCESS;
+}
 
 void RunChildProc(TestRunner::TestCase procChild)
 {
diff --git a/modules/test/src/test_runner_multiprocess.cpp b/modules/test/src/test_runner_multiprocess.cpp
new file mode 100644 (file)
index 0000000..c242480
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * 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_runner_multiprocess.cpp
+ * @author      Marcin Niesluchowski (m.niesluchow@samsung.com)
+ * @version     1.0
+ * @brief       This file is the implementation file of multiprocess test runner
+ */
+
+#include <sys/file.h>
+#include <dpl/test/test_runner.h>
+#include <dpl/test/test_runner_child.h>
+#include <dpl/test/test_runner_multiprocess.h>
+#include <poll.h>
+#include <limits.h>
+#include <sys/wait.h>
+
+namespace {
+
+const int MULTI_TEST_ERROR    = -1;
+const int MULTI_TEST_PASS     = 0;
+const int MULTI_TEST_FAILED   = 1;
+const int MULTI_TEST_IGNORED  = 2;
+const int MULTI_TEST_INTERNAL = 3;
+
+}
+
+namespace DPL {
+namespace Test {
+
+SimplePipeWrapper::SimplePipeWrapper()
+: PipeWrapper()
+{
+
+}
+
+SimplePipeWrapper::~SimplePipeWrapper()
+{
+
+}
+
+PipeWrapper::Status SimplePipeWrapper::send(std::string &message)
+{
+    if (m_pipefd[1] == PIPE_CLOSED) {
+           return ERROR;
+    }
+
+    if (message.size() > PIPE_BUF-1) {
+        return ERROR;
+    }
+
+    char buffer[PIPE_BUF] = { 0 };
+
+
+    for(unsigned int i = 0; i < message.size(); ++i) {
+        buffer[i] = message[i];
+    }
+
+    return writeHelp(buffer, PIPE_BUF);
+}
+
+PipeWrapper::Status SimplePipeWrapper::receive(std::string &data, bool &empty, time_t deadline)
+{
+    if (m_pipefd[0] == PIPE_CLOSED) {
+        return ERROR;
+    }
+
+    empty = false;
+
+    data.resize(PIPE_BUF);
+
+    char buffer[PIPE_BUF] = { 0 };
+
+    int ready = 0;
+    while (ready != PIPE_BUF) {
+        time_t wait = deadline - time(0);
+        wait = wait < 1 ? 1 : wait;
+        pollfd fds = { m_pipefd[0], POLLIN, 0 };
+
+        int pollReturn = poll(&fds, 1, wait * 1000);
+
+        if (pollReturn == 0) {
+            return TIMEOUT; // Timeout
+        }
+
+        if (pollReturn < -1) {
+            return ERROR;
+        }
+        int ret = read(m_pipefd[0], &buffer[ready], PIPE_BUF - ready);
+        if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
+            continue;
+        }
+
+        if (ret == -1) {
+            closeHelp(0);
+            return ERROR;
+        }
+        if (ret == 0) {
+            empty = true;
+            break;
+        }
+
+        ready += ret;
+    }
+
+
+    for(unsigned int i = 0; i < PIPE_BUF; ++i){
+        if(buffer[i] == 0) {
+            data.resize(i);
+            return SUCCESS;
+        }
+        data[i] = buffer[i];
+    }
+
+    return ERROR;
+}
+
+void RunMultiProc(TestRunner::TestCase procMulti)
+{
+    SimplePipeWrapper pipe;
+    int code = MULTI_TEST_PASS;
+    std::string msg = "";
+    int pipeReturn;
+
+    int waitStatus;
+
+    pid_t top_pid = getpid();
+
+    if (!pipe.isReady()) {
+        throw TestRunner::TestFailed("Pipe creation failed");
+    }
+    // pipe
+
+    try {
+        procMulti();
+    } catch (const TestRunner::TestFailed &e) {
+        code = MULTI_TEST_FAILED;
+        msg = e.GetMessage();
+    } catch (const TestRunner::Ignored &e) {
+        code = MULTI_TEST_IGNORED;
+        msg = e.GetMessage();
+    } catch (const DPL::Exception &e) {
+        code = MULTI_TEST_INTERNAL;
+        msg = "DPL exception:" + e.GetMessage();
+    } catch (const std::exception &) {
+        code = MULTI_TEST_INTERNAL;
+        msg = "std exception";
+    } catch (...) {
+        // Unknown exception failure
+        code = MULTI_TEST_INTERNAL;
+        msg = "unknown exception";
+    }
+
+    while (true) {
+        pid_t child_pid = wait(&waitStatus);
+        if (child_pid == -1) {
+            if (errno == ECHILD) {
+                if (top_pid == getpid()) {
+                    std::string recMsg="";
+
+                    pipe.setUsage(PipeWrapper::READONLY);
+
+                    bool empty=false;
+                    while(true) {
+                        pipeReturn = pipe.receive(recMsg, empty, time(0) + 10);
+
+                        if (empty) {
+                            break;
+                        }
+                        if (pipeReturn == PipeWrapper::ERROR) {
+                            pipe.closeAll();
+                            throw TestRunner::TestFailed("Reading pipe error");
+                        } else if (pipeReturn == PipeWrapper::TIMEOUT) {
+                            pipe.closeAll();
+                            throw TestRunner::TestFailed("Timeout error");
+                        }
+                        msg = msg + "\n" + recMsg;
+                    }
+                    pipe.closeAll();
+
+                    switch(code) {
+                    case MULTI_TEST_PASS:
+                        return;
+                    case MULTI_TEST_FAILED:
+                        throw TestRunner::TestFailed(msg);
+                    case MULTI_TEST_IGNORED:
+                        throw TestRunner::Ignored(msg);
+                    case MULTI_TEST_INTERNAL:
+                        throw TestRunner::TestFailed(msg);
+                    default:
+                        throw TestRunner::TestFailed(msg);
+                    }
+                } else {
+                    pipe.setUsage(PipeWrapper::WRITEONLY);
+
+                    pipeReturn = pipe.send(msg);
+
+                    if (pipeReturn == PipeWrapper::ERROR) {
+                        pipe.closeAll();
+                        code = MULTI_TEST_ERROR;
+                    }
+
+                    exit(code);
+                }
+            }
+        } else if (WIFEXITED(waitStatus)) {
+            if ((signed char)WEXITSTATUS(waitStatus) == MULTI_TEST_FAILED) {
+                switch (code) {
+                    case MULTI_TEST_PASS:
+                        code = MULTI_TEST_FAILED;
+                        break;
+                    case MULTI_TEST_FAILED:
+                        break;
+                    case MULTI_TEST_IGNORED:
+                        code = MULTI_TEST_FAILED;
+                        break;
+                    case MULTI_TEST_INTERNAL:
+                        break;
+                    default:
+                        break;
+                    }
+            } else if ((signed char)WEXITSTATUS(waitStatus) == MULTI_TEST_IGNORED) {
+                switch (code) {
+                case MULTI_TEST_PASS:
+                    code = MULTI_TEST_IGNORED;
+                    break;
+                case MULTI_TEST_FAILED:
+                    break;
+                case MULTI_TEST_IGNORED:
+                    break;
+                case MULTI_TEST_INTERNAL:
+                    break;
+                default:
+                    break;
+                }
+            } else if ((signed char)WEXITSTATUS(waitStatus) == MULTI_TEST_INTERNAL) {
+                switch (code) {
+                case MULTI_TEST_PASS:
+                    code = MULTI_TEST_INTERNAL;
+                    break;
+                case MULTI_TEST_FAILED:
+                    code = MULTI_TEST_INTERNAL;
+                    break;
+                case MULTI_TEST_IGNORED:
+                    code = MULTI_TEST_INTERNAL;
+                    break;
+                case MULTI_TEST_INTERNAL:
+                    break;
+                default:
+                    break;
+                }
+            } else  if ((signed char)WEXITSTATUS(waitStatus) != MULTI_TEST_PASS) {
+                code = MULTI_TEST_ERROR;
+                msg = "PROCESS BAD CODE RETURN";
+            }
+        }
+    }
+}
+} // namespace Test
+} // namespace DPL
index ff7b544..67ffd43 100644 (file)
@@ -116,10 +116,17 @@ public:
      * @return full path
      */
     std::string Fullpath() const;
+    /**
+     * @brief Extension
+     * @return extension
+     */
+    std::string Extension() const;
 
     bool Exists() const;
     bool IsDir() const;
     bool IsFile() const;
+    bool ExistsAndIsFile() const;
+    bool ExistsAndIsDir() const;
     bool IsSymlink() const;
     std::size_t Size() const;
     /**
index 51b54aa..ea1653f 100644 (file)
@@ -163,6 +163,23 @@ std::string Path::Fullpath() const
     return std::string ("/") + ret;
 }
 
+std::string Path::Extension() const
+{
+    if(m_parts.empty()) return "";
+
+    const std::string& last = *--m_parts.end();
+
+    std::string::size_type pos = last.find_last_of(".");
+    if(pos != std::string::npos)
+    {
+        return last.substr(pos + 1);
+    }
+    else
+    {
+        return "";
+    }
+}
+
 //foreach
 Path::Iterator Path::begin() const
 {
@@ -215,6 +232,30 @@ bool Path::IsFile() const
     return S_ISREG(tmp.st_mode);
 }
 
+bool Path::ExistsAndIsFile() const
+{
+    bool flag = false;
+    Try
+    {
+        flag = this->IsFile();
+    } Catch (Path::NotExists) {
+        LogPedantic(*this << "is not a file.");
+    }
+    return flag;
+}
+
+bool Path::ExistsAndIsDir() const
+{
+    bool flag = false;
+    Try
+    {
+        flag = this->IsDir();
+    } Catch (Path::NotExists) {
+        LogPedantic(*this << "is not a directory.");
+    }
+    return flag;
+}
+
 bool Path::IsSymlink() const
 {
     struct stat tmp;
@@ -316,23 +357,16 @@ bool Path::isSubPath(const Path & other) const
 
 bool Path::hasExtension(const std::string& extension) const
 {
-    LogDebug("Looking for extension " << extension << " in: " << this->Filename());
-
-    size_t extLen = extension.length();
-
-    if(m_parts.empty()) return false;
-    if(extLen == 0) return false;
-
-    const std::string& last = *--m_parts.end();
-    size_t lastLen = last.length();
-
-    if(lastLen < (1 + extLen)) return false;
-
-    const char last_tmp = last[ lastLen - (1 + extLen) ];
-    if(last_tmp != '.') return false;
+    LogPedantic("Looking for extension " << extension);
 
-    if(last.substr(lastLen - extLen) != extension) return false;
-    return true;
+    if(Extension() == extension)
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
 }
 
 void MakeDir(const Path & path, mode_t mode)
index 0eba4e4..ab41158 100644 (file)
@@ -292,6 +292,21 @@ inline const char* GetBackupDatabaseSuffix()
 {
     return ".backup";
 }
+
+inline const char* GetManifestPath()
+{
+    return "/opt/share/packages";
+}
+
+inline const char* GetPreloadManifestPath()
+{
+    return "/usr/share/packages";
+}
+
+inline const char* GetRecoveryStatusPath()
+{
+    return "/usr/share/packages/.recovery/wgt";
+}
 } // namespace GlobalConfig
 } // namespace WrtDB
 
index 5c31d04..4d6817a 100644 (file)
@@ -1,7 +1,7 @@
 #git:framework/web/wrt-commons
 Name:       wrt-commons
 Summary:    Wrt common library
-Version:    0.2.150
+Version:    0.2.151
 Release:    1
 Group:      Development/Libraries
 License:    Apache License, Version 2.0
index 48fb045..500e52b 100644 (file)
@@ -23,6 +23,7 @@ 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_multiprocess.cpp
     ${TESTS_DIR}/test/runner_child.cpp
     ${TESTS_DIR}/test/test_process_pipe.cpp
 )
diff --git a/tests/test/runner_multiprocess.cpp b/tests/test/runner_multiprocess.cpp
new file mode 100644 (file)
index 0000000..fcac88e
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * 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    runner_multiprocess.cpp
+ * @author  Marcin Niesluchowski (m.niesluchow@samsung.com)
+ * @version 1.0
+ * @brief   Implementation file for test cases for engine internal tests
+ */
+
+#include <dpl/test/test_runner_multiprocess.h>
+#include <dpl/test/test_runner.h>
+#include <dpl/log/log.h>
+#include <list>
+
+namespace {
+std::list<std::string> split_string(std::string str, std::string delimiter)
+{
+    size_t pos = 0;
+    std::string token;
+    std::list<std::string> stringList;
+    while ((pos = str.find(delimiter)) != std::string::npos) {
+        token = str.substr(0, pos);
+        stringList.push_back(token);
+        str.erase(0, pos + delimiter.length());
+    }
+    if(str.length() != 0){
+        stringList.push_back(token);
+    }
+    return stringList;
+}
+}
+
+#define RUNNER_MULTIPROCESS_TEST_EXPECT(name, messages)                        \
+    static void testExpectFunction##name();                                    \
+    RUNNER_TEST(name)                                                          \
+    {                                                                          \
+        Try                                                                    \
+        {                                                                      \
+            DPL::Test::RunMultiProc(&testExpectFunction##name);                \
+        }                                                                      \
+        Catch(DPL::Test::TestRunner::TestFailed)                               \
+        {                                                                      \
+            std::string eMsg = messages;                                       \
+            std::list<std::string> eMessages = split_string(eMsg, "|");        \
+            std::string rMessage = _rethrown_exception.GetMessage();           \
+            if(eMsg.length() == 0 && rMessage.length() != 0) {                 \
+                RUNNER_ASSERT_MSG(false, rMessage);                            \
+            }                                                                  \
+            bool failedFound = false;                                          \
+            for(std::list<std::string>::iterator it = eMessages.begin();       \
+                it != eMessages.end();                                         \
+                ++it)                                                          \
+            {                                                                  \
+                if (!(*it).compare("TEST_FAILED")) {                           \
+                    failedFound = true;                                        \
+                    continue;                                                  \
+                }                                                              \
+                RUNNER_ASSERT_MSG(rMessage.find(*it)!=std::string::npos,       \
+                    "Key word " << *it << " not found in " << rMessage);       \
+            }                                                                  \
+            RUNNER_ASSERT_MSG(                                                 \
+                rMessage.find("Reading pipe error")==std::string::npos,        \
+                "Reading pipe error");                                         \
+            RUNNER_ASSERT_MSG(                                                 \
+                rMessage.find("Timeout error")==std::string::npos,             \
+                "Timeout error");                                              \
+            RUNNER_ASSERT_MSG(failedFound, "No TEST_FAILED found");            \
+        }                                                                      \
+        Catch(DPL::Test::TestRunner::Ignored)                                  \
+        {                                                                      \
+            std::string eMsg = messages;                                       \
+            std::list<std::string> eMessages = split_string(eMsg, "|");        \
+            std::string rMessage = _rethrown_exception.GetMessage();           \
+            if(eMsg.length() == 0 && rMessage.length() != 0) {                 \
+                RUNNER_ASSERT_MSG(false, rMessage);                            \
+            }                                                                  \
+            bool ignoredFound = false;                                         \
+            for(std::list<std::string>::iterator it = eMessages.begin();       \
+                it != eMessages.end();                                         \
+                ++it)                                                          \
+            {                                                                  \
+                if (!(*it).compare("TEST_IGNORED")) {                           \
+                    ignoredFound = true;                                       \
+                    continue;                                                  \
+                }                                                              \
+                RUNNER_ASSERT_MSG(rMessage.find(*it)!=std::string::npos,       \
+                    "Key word " << *it << " not found in " << rMessage);       \
+            }                                                                  \
+            RUNNER_ASSERT_MSG(                                                 \
+                rMessage.find("Reading pipe error")==std::string::npos,        \
+                "Reading pipe error");                                         \
+            RUNNER_ASSERT_MSG(                                                 \
+                rMessage.find("Timeout error")==std::string::npos,             \
+                "Timeout error");                                              \
+            RUNNER_ASSERT_MSG(ignoredFound, "No TEST_IGNORED found");          \
+        }                                                                      \
+    }                                                                          \
+    void testExpectFunction##name()                                            \
+
+RUNNER_TEST_GROUP_INIT(DPL_TESTS_TEST_MULTIPROCESS)
+
+RUNNER_MULTIPROCESS_TEST_EXPECT(tm00_pass, "")
+{
+    RUNNER_ASSERT_MSG(1, "This test should pass");
+}
+
+RUNNER_MULTIPROCESS_TEST_EXPECT(tm01_pass, "")
+{
+    pid_t pid = fork();
+    if(pid){
+        sleep(2);
+        RUNNER_ASSERT_MSG(1, "This test should pass");
+    } else {
+        RUNNER_ASSERT_MSG(1, "This test should pass");
+    }
+    RUNNER_ASSERT_MSG(1, "This test should pass");
+}
+
+RUNNER_MULTIPROCESS_TEST_EXPECT(tm02_pass, "")
+{
+    pid_t pid = fork();
+    if(pid){
+        RUNNER_ASSERT_MSG(1, "This test should pass");
+    } else {
+        sleep(2);
+        RUNNER_ASSERT_MSG(1, "This test should pass");
+    }
+    RUNNER_ASSERT_MSG(1, "This test should pass");
+}
+
+RUNNER_MULTIPROCESS_TEST_EXPECT(tm03_pass, "")
+{
+    pid_t pid = fork();
+    if(pid){
+        pid = fork();
+        if(pid){
+            sleep(1);
+        } else {
+            sleep(2);
+        }
+    } else {
+        if(pid){
+            sleep(2);
+        } else {
+            sleep(1);
+        }
+    }
+}
+
+RUNNER_MULTIPROCESS_TEST_EXPECT(tm04_fail, "TEST_FAILED|"
+                                           "This test should fail")
+{
+    RUNNER_ASSERT_MSG(0, "This test should fail");
+}
+
+RUNNER_MULTIPROCESS_TEST_EXPECT(tm05_fail,"TEST_FAILED|"
+                                          "Test failed 1|"
+                                          "Test failed 2|"
+                                          "Test failed 3|"
+                                          "Test failed 4")
+{
+    pid_t pid = fork();
+    if(pid){
+        pid = fork();
+        if(pid){
+            RUNNER_ASSERT_MSG(0, "Test failed 1");
+        } else {
+            RUNNER_ASSERT_MSG(0, "Test failed 2");
+        }
+    } else {
+        pid = fork();
+        if(pid){
+            RUNNER_ASSERT_MSG(0, "Test failed 3");
+        } else {
+            RUNNER_ASSERT_MSG(0, "Test failed 4");
+        }
+    }
+}
+
+RUNNER_MULTIPROCESS_TEST_EXPECT(tm06_fail, "TEST_FAILED|"
+                                          "Test failed 1|"
+                                          "Test failed 2|"
+                                          "Test failed 3|"
+                                          "Test failed 4")
+{
+    pid_t pid = fork();
+    if(pid){
+        pid = fork();
+        if(pid){
+            sleep(2);
+            RUNNER_ASSERT_MSG(0, "Test failed 1");
+        } else {
+            RUNNER_ASSERT_MSG(0, "Test failed 2");
+        }
+    } else {
+        pid = fork();
+        if(pid){
+            RUNNER_ASSERT_MSG(0, "Test failed 3");
+        } else {
+            RUNNER_ASSERT_MSG(0, "Test failed 4");
+        }
+    }
+}
+
+RUNNER_MULTIPROCESS_TEST_EXPECT(tm07_fail, "TEST_FAILED|"
+                                          "Test failed 1|"
+                                          "Test failed 2|"
+                                          "Test failed 3|"
+                                          "Test failed 4")
+{
+    pid_t pid = fork();
+    if(pid){
+        pid = fork();
+        if(pid){
+            RUNNER_ASSERT_MSG(0, "Test failed 1");
+        } else {
+            RUNNER_ASSERT_MSG(0, "Test failed 2");
+        }
+    } else {
+        pid = fork();
+        if(pid){
+            sleep(2);
+            RUNNER_ASSERT_MSG(0, "Test failed 3");
+        } else {
+            RUNNER_ASSERT_MSG(0, "Test failed 4");
+        }
+    }
+}
+
+RUNNER_MULTIPROCESS_TEST_EXPECT(tm08_fail_unknown_exception, "TEST_FAILED|"
+                                                             "unknown exception")
+{
+    throw("hello");
+}
+
+RUNNER_MULTIPROCESS_TEST_EXPECT(tm09_fail_unknown_exception, "TEST_FAILED|"
+                                                            "unknown exception")
+{
+    throw(1);
+}
+
+RUNNER_MULTIPROCESS_TEST_EXPECT(tm10_ignore, "TEST_IGNORED|"
+                                             "Test ignored")
+{
+    RUNNER_IGNORED_MSG("Test ignored");
+}
+
+RUNNER_MULTIPROCESS_TEST_EXPECT(tm11_ignore, "TEST_IGNORED|"
+                                            "Test ignored 1|"
+                                            "Test ignored 2|"
+                                            "Test ignored 3|"
+                                            "Test ignored 4")
+{
+    pid_t pid = fork();
+    if(pid){
+        pid = fork();
+        if(pid){
+            RUNNER_IGNORED_MSG("Test ignored 1");
+        } else {
+            RUNNER_IGNORED_MSG("Test ignored 2");
+        }
+    } else {
+        pid = fork();
+        if(pid){
+            sleep(2);
+            RUNNER_IGNORED_MSG("Test ignored 3");
+        } else {
+            RUNNER_IGNORED_MSG("Test ignored 4");
+        }
+    }
+}
+
+RUNNER_MULTIPROCESS_TEST_EXPECT(tm12_fail, "TEST_FAILED|"
+                                          "Test failed 1|"
+                                          "Test ignored 2|"
+                                          "Test ignored 3|"
+                                          "Test ignored 4")
+{
+    pid_t pid = fork();
+    if(pid){
+        pid = fork();
+        if(pid){
+            RUNNER_ASSERT_MSG(0, "Test failed 1");
+        } else {
+            RUNNER_IGNORED_MSG("Test ignored 2");
+        }
+    } else {
+        pid = fork();
+        if(pid){
+            sleep(2);
+            RUNNER_IGNORED_MSG("Test ignored 3");
+        } else {
+            RUNNER_IGNORED_MSG("Test ignored 4");
+        }
+    }
+}
index ffc8a8d..46405f9 100644 (file)
@@ -58,7 +58,7 @@ RUNNER_TEST(ProcessPipe_echo)
     npp.Close();
 
     char buffer[100] = "";
-    result.FlattenConsume(buffer, 99);
+    result.FlattenConsume(buffer, std::min(result.Size(), sizeof(buffer)));
 
     RUNNER_ASSERT_MSG(strcmp(buffer, "Test echo text\nAnd new line\n") == 0, "Echoed text in not equal");
 }
@@ -113,7 +113,7 @@ RUNNER_TEST(ProcessPipe_pipeerror_pipe)
     readAll(npp, result);
     npp.Close();
     char buffer[100] = "";
-    result.FlattenConsume(buffer, 99);
+    result.FlattenConsume(buffer, std::min(result.Size(), sizeof(buffer)));
 
     RUNNER_ASSERT_MSG(strcmp(buffer, "ls: cannot access /nonexistingdirectory: No such file or directory\n") == 0, "Ls error text in not equal");
 }
index 7ad96d2..0d29057 100644 (file)
@@ -102,6 +102,26 @@ RUNNER_TEST(path_mkfile_exists)
 }
 
 /*
+Name: path_exists_and_is_file_or_dir
+Description: test for checking for existence of directory or file
+Expected: success
+*/
+RUNNER_TEST(path_exists_and_is_file_or_dir)
+{
+    DPL::ScopedDir sd(rootTest);
+
+    Path file = Path(rootTest) / "testfile.txt";
+    MakeEmptyFile(file);
+    RUNNER_ASSERT_MSG(file.ExistsAndIsFile(), "File should exist");
+    RUNNER_ASSERT_MSG(!file.ExistsAndIsDir(), "It should not be a directory");
+
+    Path dir = Path(rootTest) / "testdir";
+    MakeDir(dir);
+    RUNNER_ASSERT_MSG(dir.ExistsAndIsDir(), "Directory should exist");
+    RUNNER_ASSERT_MSG(!dir.ExistsAndIsFile(), "Is should not be a file");
+}
+
+/*
 Name: path_mkfile_invalid_path
 Description: tries to create file in not exisitng directory
 Expected: failure at creation
@@ -842,6 +862,36 @@ Expected: Proper recognition of extensions
 */
 RUNNER_TEST(path_extension_test)
 {
+    Path path1("/path/to/file.dot");
+    Path path2("/path/to/file..dot");
+    Path path3("/path/to/file..dot.");
+    Path path4("/path/to/file..dot.dot");
+    Path path5("/path/to.dot/file");
+    Path path6("./path/to/file");
+    Path path7("./path/to/file");
+    Path path8("/path/../file.xml");
+    Path path9("/path/../file.XML");
+    Path path10("/path/../file.myfileextension");
+
+    RUNNER_ASSERT(path1.Extension() == "dot");
+    RUNNER_ASSERT(path2.Extension() == "dot");
+    RUNNER_ASSERT(path3.Extension() == "");
+    RUNNER_ASSERT(path4.Extension() == "dot");
+    RUNNER_ASSERT(path5.Extension() == "");
+    RUNNER_ASSERT(path6.Extension() == "");
+    RUNNER_ASSERT(path7.Extension() == "");
+    RUNNER_ASSERT(path8.Extension() == "xml");
+    RUNNER_ASSERT(path9.Extension() != "xml");
+    RUNNER_ASSERT(path10.Extension() == "myfileextension");
+}
+
+/*
+Name: path_has_extension_test
+Description: Tests if file extension is correct
+Expected: Proper recognition of extensions
+*/
+RUNNER_TEST(path_has_extension_test)
+{
 
     Path dirTest = Path("extension");
 
@@ -873,7 +923,6 @@ RUNNER_TEST(path_extension_test)
     RUNNER_ASSERT_MSG(!path6.hasExtension(".JS"),
             "Wrong argument in hasExtension() function");
 
-    RUNNER_ASSERT_MSG(!path3.hasExtension(""), "Extension length is 0");
-
-    RUNNER_ASSERT_MSG(!path4.hasExtension(""), "Not a directory");
-}
\ No newline at end of file
+    RUNNER_ASSERT_MSG(path3.hasExtension(""), "Extension length should be 0");
+    RUNNER_ASSERT_MSG(path4.hasExtension(""), "There should be no extension");
+}