2 * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file test_runner_multiprocess.cpp
18 * @author Marcin Niesluchowski (m.niesluchow@samsung.com)
20 * @brief This file is the implementation file of multiprocess test runner
24 #include <dpl/test/test_runner.h>
25 #include <dpl/test/test_runner_child.h>
26 #include <dpl/test/test_runner_multiprocess.h>
34 const int MULTI_TEST_ERROR = -1;
35 const int MULTI_TEST_PASS = 0;
36 const int MULTI_TEST_FAILED = 1;
37 const int MULTI_TEST_IGNORED = 2;
38 const int MULTI_TEST_INTERNAL = 3;
45 SimplePipeWrapper::SimplePipeWrapper()
51 SimplePipeWrapper::~SimplePipeWrapper()
56 PipeWrapper::Status SimplePipeWrapper::send(std::string &message)
58 if (m_pipefd[1] == PIPE_CLOSED) {
62 if (message.size() > PIPE_BUF-1) {
66 char buffer[PIPE_BUF] = { 0 };
69 for(unsigned int i = 0; i < message.size(); ++i) {
70 buffer[i] = message[i];
73 return writeHelp(buffer, PIPE_BUF);
76 PipeWrapper::Status SimplePipeWrapper::receive(std::string &data, bool &empty, time_t deadline)
78 if (m_pipefd[0] == PIPE_CLOSED) {
84 data.resize(PIPE_BUF);
86 char buffer[PIPE_BUF] = { 0 };
89 while (ready != PIPE_BUF) {
90 time_t wait = deadline - time(0);
91 wait = wait < 1 ? 1 : wait;
92 pollfd fds = { m_pipefd[0], POLLIN, 0 };
94 int pollReturn = poll(&fds, 1, wait * 1000);
96 if (pollReturn == 0) {
97 return TIMEOUT; // Timeout
100 if (pollReturn < -1) {
103 int ret = read(m_pipefd[0], &buffer[ready], PIPE_BUF - ready);
104 if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
121 for(unsigned int i = 0; i < PIPE_BUF; ++i){
132 void RunMultiProc(TestRunner::TestCase procMulti)
134 SimplePipeWrapper pipe;
135 int code = MULTI_TEST_PASS;
136 std::string msg = "";
141 pid_t top_pid = getpid();
143 if (!pipe.isReady()) {
144 throw TestRunner::TestFailed("Pipe creation failed");
150 } catch (const TestRunner::TestFailed &e) {
151 code = MULTI_TEST_FAILED;
152 msg = e.GetMessage();
153 } catch (const TestRunner::Ignored &e) {
154 code = MULTI_TEST_IGNORED;
155 msg = e.GetMessage();
156 } catch (const DPL::Exception &e) {
157 code = MULTI_TEST_INTERNAL;
158 msg = "DPL exception:" + e.GetMessage();
159 } catch (const std::exception &) {
160 code = MULTI_TEST_INTERNAL;
161 msg = "std exception";
163 // Unknown exception failure
164 code = MULTI_TEST_INTERNAL;
165 msg = "unknown exception";
169 pid_t child_pid = wait(&waitStatus);
170 if (child_pid == -1) {
171 if (errno == ECHILD) {
172 if (top_pid == getpid()) {
173 std::string recMsg="";
175 pipe.setUsage(PipeWrapper::READONLY);
179 pipeReturn = pipe.receive(recMsg, empty, time(0) + 10);
184 if (pipeReturn == PipeWrapper::ERROR) {
186 throw TestRunner::TestFailed("Reading pipe error");
187 } else if (pipeReturn == PipeWrapper::TIMEOUT) {
189 throw TestRunner::TestFailed("Timeout error");
191 msg = msg + "\n" + recMsg;
196 case MULTI_TEST_PASS:
198 case MULTI_TEST_FAILED:
199 throw TestRunner::TestFailed(msg);
200 case MULTI_TEST_IGNORED:
201 throw TestRunner::Ignored(msg);
202 case MULTI_TEST_INTERNAL:
203 throw TestRunner::TestFailed(msg);
205 throw TestRunner::TestFailed(msg);
208 pipe.setUsage(PipeWrapper::WRITEONLY);
210 pipeReturn = pipe.send(msg);
212 if (pipeReturn == PipeWrapper::ERROR) {
214 code = MULTI_TEST_ERROR;
220 } else if (WIFEXITED(waitStatus)) {
221 if ((signed char)WEXITSTATUS(waitStatus) == MULTI_TEST_FAILED) {
223 case MULTI_TEST_PASS:
224 code = MULTI_TEST_FAILED;
226 case MULTI_TEST_FAILED:
228 case MULTI_TEST_IGNORED:
229 code = MULTI_TEST_FAILED;
231 case MULTI_TEST_INTERNAL:
236 } else if ((signed char)WEXITSTATUS(waitStatus) == MULTI_TEST_IGNORED) {
238 case MULTI_TEST_PASS:
239 code = MULTI_TEST_IGNORED;
241 case MULTI_TEST_FAILED:
243 case MULTI_TEST_IGNORED:
245 case MULTI_TEST_INTERNAL:
250 } else if ((signed char)WEXITSTATUS(waitStatus) == MULTI_TEST_INTERNAL) {
252 case MULTI_TEST_PASS:
253 code = MULTI_TEST_INTERNAL;
255 case MULTI_TEST_FAILED:
256 code = MULTI_TEST_INTERNAL;
258 case MULTI_TEST_IGNORED:
259 code = MULTI_TEST_INTERNAL;
261 case MULTI_TEST_INTERNAL:
266 } else if ((signed char)WEXITSTATUS(waitStatus) != MULTI_TEST_PASS) {
267 code = MULTI_TEST_ERROR;
268 msg = "PROCESS BAD CODE RETURN";