${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
${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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
${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
)
${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
)
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
--- /dev/null
+/*
+ * 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
#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;
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)
{
--- /dev/null
+/*
+ * 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
* @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;
/**
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
{
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;
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)
{
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
#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
# 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
)
--- /dev/null
+/*
+ * 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");
+ }
+ }
+}
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");
}
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");
}
RUNNER_ASSERT_MSG(cannotCreate2ndTime, "File created should not be able to be created second time");
}
+/*
+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: 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");
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");
+}