/*
- * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2013-2015 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/*
+/**
* @file test_runner_child.cpp
* @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
* @version 1.0
* @brief This file is the implementation file of test runner
*/
#include <stddef.h>
+#include <dpl/assert.h>
+#include <dpl/test/test_failed.h>
+#include <dpl/test/test_ignored.h>
#include <dpl/test/test_runner.h>
#include <dpl/test/test_runner_child.h>
#include <dpl/test/test_results_collector.h>
const int CHILD_TEST_PASS = 1;
const int CHILD_TEST_IGNORED = 2;
-const int MSG_TYPE_MESSAGE = 0; // sizeof(Message) + Message
-const int MSG_TYPE_PERF_TIME = 1; // perfTime + maxTime
-
int closeOutput() {
int devnull;
int retcode = -1;
std::ostringstream output;
output << toBinaryString(code);
- output << toBinaryString(MSG_TYPE_MESSAGE);
output << toBinaryString(static_cast<int>(message.size()));
output << message;
return SUCCESS;
}
-PipeWrapper::Status PipeWrapper::sendTime(int code,
- std::chrono::system_clock::duration time,
- std::chrono::system_clock::duration timeMax)
+PipeWrapper::Status PipeWrapper::sendPerformance(const ConstPerformanceResultPtr &performance)
{
+ int foo = 0;
if (m_pipefd[1] == PIPE_CLOSED) {
return ERROR;
}
+ if (!performance)
+ return writeHelp(&foo, sizeof(int));
- std::ostringstream output;
- output << toBinaryString(code);
- output << toBinaryString(MSG_TYPE_PERF_TIME);
- output << toBinaryString(time);
- output << toBinaryString(timeMax);
-
- std::string binary = output.str();
+ std::string binary = performance->ToBinaryString();
int size = binary.size();
if ((writeHelp(&size,
}
PipeWrapper::Status PipeWrapper::receive(int &code,
- int &msgType,
std::string &data,
- std::chrono::system_clock::duration &time,
- std::chrono::system_clock::duration &timeMax,
+ PerformanceResultPtr &performance,
time_t deadline)
{
if (m_pipefd[0] == PIPE_CLOSED) {
queue.AppendCopy(&buffer[0], size);
queue.FlattenConsume(&code, sizeof(int));
- queue.FlattenConsume(&msgType, sizeof(int));
-
- switch (msgType) {
- case MSG_TYPE_MESSAGE:
- queue.FlattenConsume(&size, sizeof(int));
-
- buffer.resize(size);
-
- queue.FlattenConsume(&buffer[0], size);
- data.assign(buffer.begin(), buffer.end());
- break;
- case MSG_TYPE_PERF_TIME:
- queue.FlattenConsume(&time, sizeof(std::chrono::system_clock::duration));
- queue.FlattenConsume(&timeMax, sizeof(std::chrono::system_clock::duration));
- break;
- default:
- return ERROR;
+ queue.FlattenConsume(&size, sizeof(int));
+
+ buffer.resize(size);
+
+ queue.FlattenConsume(&buffer[0], size);
+ data.assign(buffer.begin(), buffer.end());
+
+ if (code != CHILD_TEST_PASS)
+ return SUCCESS;
+
+ if ((ret = readHelp(&size, sizeof(int), deadline)) != SUCCESS) {
+ return ret;
}
+
+ if (size == 0) {
+ performance = nullptr;
+ return SUCCESS;
+ }
+
+ buffer.resize(size);
+
+ if ((ret = readHelp(buffer.data(), size, deadline)) != SUCCESS) {
+ return ret;
+ }
+
+ queue.AppendCopy(buffer.data(), size);
+
+ performance.reset(new PerformanceResult(queue));
} catch (DPL::BinaryQueue::Exception::Base &e) {
return ERROR;
}
return std::string(buffer, buffer + sizeof(int));
}
-std::string PipeWrapper::toBinaryString(std::chrono::system_clock::duration data)
-{
- char buffer[sizeof(std::chrono::system_clock::duration)];
- memcpy(buffer, &data, sizeof(std::chrono::system_clock::duration));
- return std::string(buffer, buffer + sizeof(std::chrono::system_clock::duration));
-}
-
void PipeWrapper::closeHelp(int desc)
{
if (m_pipefd[desc] != PIPE_CLOSED) {
return SUCCESS;
}
-void RunChildProc(TestRunner::TestCase procChild)
+void RunChildProc(const std::function<void(void)> &testFunc)
{
PipeWrapper pipe;
if (!pipe.isReady()) {
- throw TestRunner::TestFailed("Pipe creation failed");
+ throw TestFailed("Pipe creation failed");
}
pid_t pid = fork();
if (pid == -1) {
- throw TestRunner::TestFailed("Child creation failed");
+ throw TestFailed("Child creation failed");
}
if (pid != 0) {
pipe.setUsage(PipeWrapper::READONLY);
int code;
- int msgType;
- std::chrono::system_clock::duration time_m;
- std::chrono::system_clock::duration timeMax_m;
std::string message;
+ PerformanceResultPtr performance;
- int pipeReturn = pipe.receive(code, msgType, message, time_m, timeMax_m, time(0) + 10);
+ int pipeReturn = pipe.receive(code, message, performance, time(0) + 10);
if (pipeReturn != PipeWrapper::SUCCESS) { // Timeout or reading error
pipe.closeAll();
waitpid(pid, &status, 0);
if (pipeReturn == PipeWrapper::TIMEOUT) {
- throw TestRunner::TestFailed("Timeout");
+ throw TestFailed("Timeout");
}
if (pipeReturn == PipeWrapper::ERROR) {
- throw TestRunner::TestFailed("Reading pipe error");
+ throw TestFailed("Reading pipe error");
}
- if (code == CHILD_TEST_PASS && msgType == MSG_TYPE_PERF_TIME) {
- DPL::Test::TestRunnerSingleton::Instance().setCurrentTestCasePerformanceResult(true,
- time_m,
- timeMax_m);
- }
+ TestRunnerSingleton::Instance().setCurrentTestCasePerformanceResult(performance);
if (code == CHILD_TEST_FAIL) {
- throw TestRunner::TestFailed(message);
+ throw TestFailed(message);
} else if (code == CHILD_TEST_IGNORED) {
- throw TestRunner::Ignored(message);
+ throw TestIgnored(message);
}
} else {
// child code
// End Runner after current test
TestRunnerSingleton::Instance().Terminate();
- int code = CHILD_TEST_PASS;
- std::string msg;
- bool isPerformanceTest;
- std::chrono::system_clock::duration time_m;
- std::chrono::system_clock::duration timeMax_m;
-
bool allowLogs = TestRunnerSingleton::Instance().GetAllowChildLogs();
close(STDIN_FILENO);
pipe.setUsage(PipeWrapper::WRITEONLY);
- try {
- procChild();
- } catch (const DPL::Test::TestRunner::TestFailed &e) {
- msg = e.GetMessage();
- code = CHILD_TEST_FAIL;
- } catch (const DPL::Test::TestRunner::Ignored &e) {
- msg = e.GetMessage();
- code = CHILD_TEST_IGNORED;
- } catch (...) { // catch all exception generated by "user" code
- msg = "unhandled exeception";
- code = CHILD_TEST_FAIL;
+ int code;
+ std::string msg;
+ switch (TryCatch(testFunc, msg)) {
+ case TestResult::FailStatus::FAILED:
+ code = CHILD_TEST_FAIL;
+ break;
+ case TestResult::FailStatus::IGNORED:
+ code = CHILD_TEST_IGNORED;
+ break;
+ case TestResult::FailStatus::NONE:
+ code = CHILD_TEST_PASS;
+ break;
+ default:
+ Assert(false && "Unhandled fail status");
}
if (allowLogs) {
closeOutput();
}
- DPL::Test::TestRunnerSingleton::Instance().getCurrentTestCasePerformanceResult(isPerformanceTest,
- time_m,
- timeMax_m);
-
- if (code == CHILD_TEST_PASS && isPerformanceTest){
- pipe.sendTime(code,
- time_m,
- timeMax_m);
- } else {
- pipe.send(code, msg);
+ pipe.send(code, msg);
+ if (code == CHILD_TEST_PASS){
+ pipe.sendPerformance(TestRunnerSingleton::Instance() \
+ .getCurrentTestCasePerformanceResult());
}
}
}