2 * Copyright (c) 2011 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.cpp
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19 * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
21 * @brief This file is the implementation file of test runner
23 #include <dpl/test/test_runner.h>
24 #include <dpl/test/test_results_collector.h>
25 #include <dpl/exception.h>
26 #include <dpl/scoped_free.h>
27 #include <dpl/foreach.h>
28 #include <dpl/log/log.h>
29 #include <dpl/colors.h>
37 #include <dpl/singleton_impl.h>
38 IMPLEMENT_SINGLETON(DPL::Test::TestRunner)
45 namespace // anonymous
48 std::string BaseName(std::string aPath)
50 ScopedFree<char> path(strdup(aPath.c_str()));
51 if (NULL == path.Get())
53 throw std::bad_alloc();
55 char* baseName = basename(path.Get());
56 std::string retValue = baseName;
60 } // namespace anonymous
62 //! \brief Failed test message creator
64 //! \param[in] aTest string for tested expression
65 //! \param[in] aFile source file name
66 //! \param[in] aLine source file line
67 //! \param[in] aMessage error message
68 TestRunner::TestFailed::TestFailed(const char* aTest,
71 const std::string &aMessage)
73 std::ostringstream assertMsg;
74 assertMsg << "[" << BaseName(aFile) << ":" << aLine
75 << "] Assertion failed ("
76 << aTest << ") " << aMessage;
77 m_message = assertMsg.str();
80 void TestRunner::RegisterTest(const char *testName, TestCase proc)
82 m_testGroups[m_currentGroup].push_back(TestCaseStruct(testName, proc));
85 void TestRunner::InitGroup(const char* name)
87 m_currentGroup = name;
91 TestRunner::Status TestRunner::RunTestCase(const TestCaseStruct& testCase)
97 catch (const TestFailed &e)
99 // Simple test failure
100 m_collector->CollectResult(testCase.name,
102 TestResultsCollectorBase::FailStatus::FAILED,
106 catch (const Ignored &e)
108 // Simple test have to be implemented
109 m_collector->CollectResult(testCase.name,
111 TestResultsCollectorBase::FailStatus::IGNORED,
116 catch (const ToDo &e)
118 // Simple test have to be implemented
119 m_collector->CollectResult(testCase.name,
121 TestResultsCollectorBase::FailStatus::TODO,
126 catch (const DPL::Exception &e)
128 // DPL exception failure
129 m_collector->CollectResult(testCase.name,
131 TestResultsCollectorBase::FailStatus::INTERNAL,
137 catch (const std::exception &)
139 // std exception failure
140 m_collector->CollectResult(testCase.name,
142 TestResultsCollectorBase::FailStatus::INTERNAL,
149 // Unknown exception failure
150 m_collector->CollectResult(testCase.name,
152 TestResultsCollectorBase::FailStatus::INTERNAL,
153 "unknown exception");
158 m_collector->CollectResult(testCase.name,
160 TestResultsCollectorBase::FailStatus::NONE);
165 void TestRunner::RunTests()
167 using namespace DPL::Colors::Text;
170 m_collector->Start();
172 fprintf(stderr, "%s%s%s\n", GREEN_BEGIN, "Running tests...", GREEN_END);
173 FOREACH(group, m_testGroups) {
174 TestCaseStructList list = group->second;
176 m_collector->CollectCurrentTestGroupName(group->first);
179 for (TestCaseStructList::const_iterator iterator = list.begin();
180 iterator != list.end();
183 TestCaseStruct test = *iterator;
184 if (m_startTestId == test.name)
187 if (m_startTestId.empty()) {
194 m_collector->Finish();
196 fprintf(stderr, "%s%s%s\n\n", GREEN_BEGIN, "Finished", GREEN_END);
199 void TestRunner::Banner()
201 using namespace DPL::Colors::Text;
215 void TestRunner::InvalidArgs()
217 using namespace DPL::Colors::Text;
221 "Invalid parameters!",
225 void TestRunner::Usage()
227 fprintf(stderr, "Usage: runner [options]\n\n");
228 fprintf(stderr, "Output type:\n");
229 fprintf(stderr, " --output=<output type>\n");
230 fprintf(stderr, " possible output types:\n");
231 FOREACH (type, TestResultsCollectorBase::GetCollectorsNames()) {
232 fprintf(stderr, " --output=%s\n", type->c_str());
234 fprintf(stderr, "Other parameters:\n");
236 " --regexp='regexp'\t Only selected tests"
237 " which names match regexp run\n\n");
238 fprintf(stderr, " --start=<test id>\tStart from concrete test id");
239 fprintf(stderr, " --group=<group name>\t Run tests only from one group\n");
240 fprintf(stderr, " --list\t Show a list of Test IDs\n");
241 fprintf(stderr, " --listgroups\t Show a list of Test Group names \n");
242 fprintf(stderr, " --listingroup=<group name>\t Show a list of Test IDS in one group\n");
243 fprintf(stderr, " --help\t This help\n\n");
245 fprintf(stderr, "Output %s has specific args:\n", m_collectorName.c_str());
246 fprintf(stderr, "%s\n", m_collector->CollectorSpecificHelp().c_str());
248 fprintf(stderr, "For bug reporting, please write to:\n");
249 fprintf(stderr, "<p.dobrowolsk@samsung.com>\n");
252 int TestRunner::ExecTestRunner(int argc, char *argv[])
254 std::vector<std::string> args;
255 for (int i = 0; i < argc; ++i)
257 args.push_back(argv[i]);
259 return ExecTestRunner(args);
262 void TestRunner::MarkAssertion()
267 int TestRunner::ExecTestRunner(const ArgsList& value)
269 ArgsList args = value;
270 // Parse command line
271 if (args.size() == 1)
278 args.erase(args.begin());
280 bool showHelp = false;
282 // Parse each argument
285 std::string arg = *it;
286 const std::string regexp = "--regexp=";
287 const std::string output = "--output=";
288 const std::string groupId = "--group=";
289 const std::string listCmd = "--list";
290 const std::string startCmd = "--start=";
291 const std::string listGroupsCmd = "--listgroups";
292 const std::string listInGroup = "--listingroup=";
294 if (m_collector && m_collector->ParseCollectorSpecificArg(arg)) continue;
295 else if (arg.find(startCmd) == 0)
297 arg.erase(0, startCmd.length());
298 FOREACH(group, m_testGroups) {
299 FOREACH(tc, group->second) {
300 if (tc->name == arg) {
305 if (!m_startTestId.empty()) break;
307 if (!m_startTestId.empty()) continue;
309 fprintf(stderr, "Start test id has not been found\n");
313 else if (arg.find(groupId) == 0)
315 arg.erase(0, groupId.length());
316 TestCaseGroupMap::iterator found = m_testGroups.find(arg);
317 if (found != m_testGroups.end()) {
318 std::string name = found->first;
319 TestCaseStructList newList = found->second;
320 m_testGroups.clear();
321 m_testGroups[name] = newList;
323 fprintf(stderr, "Group %s not found\n", arg.c_str());
329 else if (arg == listCmd)
331 FOREACH(group, m_testGroups) {
332 FOREACH(test, group->second) {
333 printf("ID:%s:%s\n", group->first.c_str(), test->name.c_str());
338 else if (arg == listGroupsCmd)
340 FOREACH(group, m_testGroups) {
341 printf("GR:%s\n", group->first.c_str());
345 else if (arg.find(listInGroup) == 0)
347 arg.erase(0, listInGroup.length());
348 FOREACH(test, m_testGroups[arg]) {
349 printf("ID:%s\n", test->name.c_str());
353 else if (arg == "--help")
355 else if (arg.find(output) == 0)
357 arg.erase(0, output.length());
358 m_collector.Reset(TestResultsCollectorBase::Create(arg));
364 m_collectorName = arg;
367 else if (arg.find(regexp) == 0)
369 arg.erase(0, regexp.length());
370 if (arg.length() == 0)
377 if (arg[0] == '\'' && arg[arg.length() - 1] == '\'')
380 arg.erase(arg.length() - 1);
383 if (arg.length() == 0)
390 pcrecpp::RE re(arg.c_str());
391 FOREACH(group, m_testGroups) {
392 TestCaseStructList newList;
393 FOREACH(iterator, group->second)
395 if (re.PartialMatch(iterator->name))
397 newList.push_back(*iterator);
400 group->second = newList;
419 m_collector.Reset(TestResultsCollectorBase::Create("text"));
421 if (!m_collector->Configure()) {
422 fprintf(stderr, "Could not configure selected output");