Adding/removing those macro calls will add/remove test cases they provide. To
change tests, change body of those macro calls. Registered tests are run within
group alphabetically.
+Those macros allow additional arguments which are classes with mandatory
+methods:
+* (constructor) ()
+ Called while registering test.
+ Should not throw any exceptions
+* init(const std::string &testName)
+ Called before test case function in order of classes passed to macro.
+ Should not be forked.
+ testName argument is name of the test (first macro argument).
+* finish(void)
+ called after test case function in reversed order of classes passed to
+ macro.
+ Should not be forked.
+Created instances of those classes may be accessed from within test case body
+as argument of test case funtion is
+ std::tuple<ClassesPassed> &optionalArgsTuple
dpl-test-framework
test_runner.h
"Wrong errno on opening " << " file");
}
+class Env
+{
+public:
+ Env() { ... }
+ void init(const std::string &testName) { ... }
+ void finish() { ... }
+ void doEnv() { ... }
+};
+
+class Restore
+{
+public:
+ Restore() { ... }
+ void init(const std::string &testName) { ... }
+ void finish() { ... }
+ void doRestore() { ... }
+};
+
+RUNNER_TEST(bar_optional_args, Env, Restore)
+{
+ std::get<0>(optionalArgsTuple).doEnv();
+ std::get<1>(optionalArgsTuple).doRestore();
+}
+
int main(int argc, char *argv[])
{
SummaryCollector::Register();
#define _TESTS_COMMON_H_
#include <sys/smack.h>
+#include <dpl/test/test_case_extended.h>
#include <dpl/test/test_runner.h>
#include <dpl/test/test_runner_child.h>
#include <dpl/test/test_runner_multiprocess.h>
#include <privilege-control.h>
#include <sys/smack.h>
#include <string>
+#include <tuple>
#include <errno.h>
#include <string.h>
void symlinkSafe(const std::string &targetPath, const std::string &linkPath);
void removeDir(const std::string &path);
-#define RUNNER_TEST_SMACK(Proc) \
- void Proc(); \
- static int Static##Proc##Init() \
- { \
- if(smack_check()) \
- DPL::Test::TestRunnerSingleton::Instance().RegisterTest(#Proc, &Proc); \
- \
- return 0; \
- } \
- const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
- void Proc()
-
-#define RUNNER_TEST_NOSMACK(Proc) \
- void Proc(); \
- static int Static##Proc##Init() \
- { \
- if(!(smack_check())) \
- DPL::Test::TestRunnerSingleton::Instance().RegisterTest(#Proc, &Proc); \
- \
- return 0; \
- } \
- const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
- void Proc()
-
-#define RUNNER_CHILD_TEST_SMACK(Proc) \
- void Proc(); \
- void Proc##Child(); \
- static int Static##Proc##Init() \
- { \
- if(smack_check()) \
- DPL::Test::TestRunnerSingleton::Instance().RegisterTest(#Proc, &Proc); \
- return 0; \
- } \
- const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
- void Proc(){ \
- DPL::Test::RunChildProc(&Proc##Child); \
- } \
- void Proc##Child()
-
-#define RUNNER_CHILD_TEST_NOSMACK(Proc) \
- void Proc(); \
- void Proc##Child(); \
- static int Static##Proc##Init() \
- { \
- if(!(smack_check())) \
- DPL::Test::TestRunnerSingleton::Instance().RegisterTest(#Proc, &Proc); \
- return 0; \
- } \
- const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
- void Proc(){ \
- DPL::Test::RunChildProc(&Proc##Child); \
- } \
- void Proc##Child()
-
-#define RUNNER_MULTIPROCESS_TEST_SMACK(Proc) \
- void Proc(); \
- void Proc##Multi(); \
- static int Static##Proc##Init() \
- { \
- if(smack_check()) \
- 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()
-
-#define RUNNER_MULTIPROCESS_TEST_NOSMACK(Proc) \
- void Proc(); \
- void Proc##Multi(); \
- static int Static##Proc##Init() \
- { \
- if(!(smack_check())) \
- 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()
+
+#define RUNNER_TEST_SMACK(Proc, ...) \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
+ static int Static##Proc##Init() \
+ { \
+ if (smack_check()) \
+ DPL::Test::TestRunnerSingleton::Instance().RegisterTest( \
+ new DPL::Test::TestCaseExtended<__VA_ARGS__>(#Proc, &Proc)); \
+ return 0; \
+ } \
+ const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple DPL_UNUSED)
+
+#define RUNNER_TEST_NOSMACK(Proc, ...) \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
+ static int Static##Proc##Init() \
+ { \
+ if (!smack_check()) \
+ DPL::Test::TestRunnerSingleton::Instance().RegisterTest( \
+ new DPL::Test::TestCaseExtended<__VA_ARGS__>(#Proc, &Proc)); \
+ return 0; \
+ } \
+ const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple DPL_UNUSED)
+
+#define RUNNER_CHILD_TEST_SMACK(Proc, ...) \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
+ void Proc##Child(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
+ static int Static##Proc##Init() \
+ { \
+ if (smack_check()) \
+ DPL::Test::TestRunnerSingleton::Instance().RegisterTest( \
+ new DPL::Test::TestCaseExtended<__VA_ARGS__>(#Proc, &Proc)); \
+ return 0; \
+ } \
+ const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple) { \
+ DPL::Test::RunChildProc(std::bind(Proc##Child, optionalArgsTuple)); \
+ } \
+ void Proc##Child(std::tuple<__VA_ARGS__> &optionalArgsTuple DPL_UNUSED)
+
+#define RUNNER_CHILD_TEST_NOSMACK(Proc, ...) \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
+ void Proc##Child(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
+ static int Static##Proc##Init() \
+ { \
+ if (!smack_check()) \
+ DPL::Test::TestRunnerSingleton::Instance().RegisterTest( \
+ new DPL::Test::TestCaseExtended<__VA_ARGS__>(#Proc, &Proc)); \
+ return 0; \
+ } \
+ const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple) { \
+ DPL::Test::RunChildProc(std::bind(Proc##Child, optionalArgsTuple)); \
+ } \
+ void Proc##Child(std::tuple<__VA_ARGS__> &optionalArgsTuple DPL_UNUSED)
+
+#define RUNNER_MULTIPROCESS_TEST_SMACK(Proc, ...) \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
+ void Proc##Multi(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
+ static int Static##Proc##Init() \
+ { \
+ if (smack_check()) \
+ DPL::Test::TestRunnerSingleton::Instance().RegisterTest( \
+ new DPL::Test::TestCaseExtended<__VA_ARGS__>(#Proc, &Proc)); \
+ return 0; \
+ } \
+ const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple) { \
+ DPL::Test::RunMultiProc(std::bind(Proc##Multi, optionalArgsTuple)); \
+ } \
+ void Proc##Multi(std::tuple<__VA_ARGS__> &optionalArgsTuple DPL_UNUSED)
+
+#define RUNNER_MULTIPROCESS_TEST_NOSMACK(Proc, ...) \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
+ void Proc##Multi(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
+ static int Static##Proc##Init() \
+ { \
+ if (!smack_check()) \
+ DPL::Test::TestRunnerSingleton::Instance().RegisterTest( \
+ new DPL::Test::TestCaseExtended<__VA_ARGS__>(#Proc, &Proc)); \
+ return 0; \
+ } \
+ const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple) { \
+ DPL::Test::RunMultiProc(std::bind(Proc##Multi, optionalArgsTuple)); \
+ } \
+ void Proc##Multi(std::tuple<__VA_ARGS__> &optionalArgsTuple DPL_UNUSED)
namespace DB {
--- /dev/null
+/*
+ * Copyright (c) 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.
+ * 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_case.h
+ * @author Marcin Niesluchowski (m.niesluchow@samsung.com)
+ * @version 1.0
+ * @brief This file is the header file of TestCase class
+ */
+
+#ifndef DPL_TEST_CASE_H
+#define DPL_TEST_CASE_H
+
+#include <string>
+
+#include <dpl/test/performance_result.h>
+
+namespace DPL {
+namespace Test {
+
+class TestCase
+{
+public:
+ TestCase(const std::string &name)
+ : m_name(name) {}
+ virtual ~TestCase() {}
+
+ bool operator <(const TestCase &other) const {
+ return m_name < other.m_name;
+ }
+ bool operator ==(const TestCase &other) const {
+ return m_name == other.m_name;
+ }
+
+ const std::string& GetName() const {
+ return m_name;
+ }
+ PerformanceResultPtr GetPerformance() const {
+ return m_performance;
+ }
+ void SetPerformance(PerformanceResultPtr performance) {
+ m_performance = performance;
+ }
+
+ virtual void Test() = 0;
+ virtual void Init() = 0;
+ virtual void Finish() = 0;
+
+private:
+ std::string m_name;
+ PerformanceResultPtr m_performance;
+};
+
+typedef TestCase* TestCasePtr;
+
+} // namespace Test
+} // namespace DPL
+
+#endif // DPL_TEST_CASE_H
--- /dev/null
+/*
+ * Copyright (c) 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.
+ * 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_case_extended.h
+ * @author Marcin Niesluchowski (m.niesluchow@samsung.com)
+ * @version 1.0
+ * @brief This file is the header file of TestCaseExtended class
+ */
+
+#ifndef DPL_TEST_CASE_EXTENDED_H
+#define DPL_TEST_CASE_EXTENDED_H
+
+#include <cstddef>
+#include <functional>
+#include <string>
+#include <tuple>
+
+#include <dpl/test/test_case.h>
+
+namespace DPL {
+namespace Test {
+namespace Operations {
+
+template<size_t N, class T>
+void init(T &t, const std::string &testName) {
+ (void) t;
+ (void) testName;
+}
+
+template<size_t N, class T>
+void finish(T &t) {
+ (void) t;
+}
+
+template<size_t N, class T, typename First, typename ...Rest>
+void init(T &t, const std::string &testName) {
+ std::get<N>(t).init(testName);
+ init<N+1, T, Rest...>(t, testName);
+}
+
+template<size_t N, class T, typename First, typename ...Rest>
+void finish(T &t) {
+ std::get<N>(t).finish();
+ finish<N-1, T, Rest...>(t);
+}
+
+} // namespace Operations
+
+template<typename ...Args>
+class TestCaseExtended
+ : public TestCase
+{
+public:
+ TestCaseExtended(const std::string &name,
+ const std::function<void(std::tuple<Args...> &t)> &testFunc)
+ : TestCase(name), m_testFunc(testFunc) {}
+
+private:
+ virtual void Init() { Operations::init<0, std::tuple<Args...>, Args...>(m_tuple, GetName()); }
+ virtual void Finish() { Operations::finish<sizeof...(Args)-1, std::tuple<Args...>, Args...>(m_tuple); }
+ virtual void Test() { m_testFunc(m_tuple); }
+
+ std::tuple<Args...> m_tuple;
+ std::function<void(std::tuple<Args...> &t)> m_testFunc;
+};
+
+} // namespace Test
+} // namespace DPL
+
+#endif // DPL_TEST_CASE_EXTENDED_H
* @file test_runner.h
* @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
* @author Lukasz Wrzosek (l.wrzosek@samsung.com)
+ * @author Marcin Niesluchowski (m.niesluchow@samsung.com)
* @version 1.0
* @brief This file is the header file of test runner
*/
#include <cstdlib>
#include <cstring>
#include <exception>
+#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <dpl/gdbbacktrace.h>
#include <dpl/singleton.h>
#include <dpl/test/performance_result.h>
+#include <dpl/test/test_case.h>
+#include <dpl/test/test_case_extended.h>
#include <dpl/test/test_exception.h>
#include <dpl/test/test_failed.h>
#include <dpl/test/test_ignored.h>
void addFailReason(const std::string &reason);
- typedef void (*TestCase)();
+ ~TestRunner();
private:
- struct TestCaseStruct
- {
- std::string name;
- TestCase proc;
- PerformanceResultPtr performance;
-
- bool operator <(const TestCaseStruct &other) const
- {
- return name < other.name;
- }
-
- bool operator ==(const TestCaseStruct &other) const
- {
- return name == other.name;
- }
-
- TestCaseStruct(const std::string &n, TestCase p) :
- name(n),
- proc(p)
- {}
- };
-
- typedef std::list<TestCaseStruct> TestCaseStructList;
- typedef std::map<std::string, TestCaseStructList> TestCaseGroupMap;
+ typedef std::list<TestCasePtr> TestCaseList;
+ typedef std::map<std::string, TestCaseList> TestCaseGroupMap;
+ typedef std::set<TestCasePtr> TestCaseSet;
+
TestCaseGroupMap m_testGroups;
+ TestCaseSet m_testCaseSet;
+
+ TestCasePtr m_currentTestCase;
- TestCaseStruct * m_currentTestCase;
std::string m_currentGroup;
bool filterByXML(std::map<std::string, bool> & casesMap);
void normalizeXMLTag(std::string& str, const std::string& testcase);
- void RunTestCase(const TestCaseStruct& testCase);
+ void RunTestCase(TestCasePtr testCase);
- void setCurrentTestCase(TestCaseStruct* testCase);
- TestCaseStruct *getCurrentTestCase();
+ void setCurrentTestCase(TestCasePtr testCase);
+ TestCasePtr getCurrentTestCase();
void RunTests();
void CollectResult(const std::string& id, const TestResult &result);
public:
- void RegisterTest(const char *testName, TestCase proc);
void InitGroup(const char* name);
-
+ void RegisterTest(TestCasePtr testCase);
int ExecTestRunner(int argc, char *argv[]);
typedef std::vector<std::string> ArgsList;
int ExecTestRunner(ArgsList args);
};
typedef DPL::Singleton<TestRunner> TestRunnerSingleton;
+
+TestResult::FailStatus TryCatch(const std::function<void(void)> &func, std::string &reason);
+
}
} // namespace DPL
const int DPL_UNUSED Static##GroupName##InitVar = \
Static##GroupName##Init();
-#define RUNNER_TEST(Proc) \
- void Proc(); \
- 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()
-
+#define RUNNER_TEST(Proc, ...) \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
+ static int Static##Proc##Init() \
+ { \
+ DPL::Test::TestRunnerSingleton::Instance().RegisterTest( \
+ new DPL::Test::TestCaseExtended<__VA_ARGS__>(#Proc, &Proc)); \
+ return 0; \
+ } \
+ const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple DPL_UNUSED)
/**
* ASSERT MACROS
/*
* @file test_runner_child.h
* @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @author Marcin Niesluchowski (m.niesluchow@samsung.com)
* @version 1.0
* @brief This file is the header file of test runner
*/
#ifndef DPL_TEST_RUNNER_CHILD_H
#define DPL_TEST_RUNNER_CHILD_H
+#include <functional>
+#include <memory>
+#include <tuple>
+
+#include <dpl/availability.h>
+#include <dpl/test/test_case_extended.h>
#include <dpl/test/test_runner.h>
namespace DPL {
int m_pipefd[2];
};
-void RunChildProc(TestRunner::TestCase procChild);
+void RunChildProc(const std::function<void(void)> &testFunc);
} // namespace Test
} // namespace DPL
-#define RUNNER_CHILD_TEST(Proc) \
- void Proc(); \
- void Proc##Child(); \
- 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::RunChildProc(&Proc##Child); \
- } \
- void Proc##Child()
+#define RUNNER_CHILD_TEST(Proc, ...) \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
+ void Proc##Child(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
+ static int Static##Proc##Init() \
+ { \
+ DPL::Test::TestRunnerSingleton::Instance().RegisterTest( \
+ new DPL::Test::TestCaseExtended<__VA_ARGS__>(#Proc, &Proc)); \
+ return 0; \
+ } \
+ const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple) { \
+ DPL::Test::RunChildProc(std::bind(Proc##Child, optionalArgsTuple)); \
+ } \
+ void Proc##Child(std::tuple<__VA_ARGS__> &optionalArgsTuple DPL_UNUSED)
#endif // DPL_TEST_RUNNER_CHILD_H
/*
- * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-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.
#ifndef DPL_TEST_RUNNER_MULTIPROCESS_H
#define DPL_TEST_RUNNER_MULTIPROCESS_H
+#include <ctime>
+#include <functional>
+#include <memory>
+#include <string>
+#include <tuple>
+
+#include <dpl/availability.h>
#include <dpl/test/test_runner_child.h>
namespace DPL {
Status receive(std::string &data, bool &empty, time_t deadline);
};
-void RunMultiProc(TestRunner::TestCase procMulti);
+void RunMultiProc(const std::function<void(void)>& testFunc);
} // 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()
+#define RUNNER_MULTIPROCESS_TEST(Proc, ...) \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
+ void Proc##Multi(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
+ static int Static##Proc##Init() \
+ { \
+ DPL::Test::TestRunnerSingleton::Instance().RegisterTest( \
+ new DPL::Test::TestCaseExtended<__VA_ARGS__>(#Proc, &Proc)); \
+ return 0; \
+ } \
+ const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
+ void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple) { \
+ DPL::Test::RunMultiProc(std::bind(Proc##Multi, optionalArgsTuple)); \
+ } \
+ void Proc##Multi(std::tuple<__VA_ARGS__> &optionalArgsTuple DPL_UNUSED)
#endif // DPL_TEST_RUNNER_MULTIPROCESS_H
#include <pcrecpp.h>
#include <algorithm>
#include <cstdio>
-#include <memory.h>
+#include <exception>
+#include <functional>
+#include <memory>
+#include <string>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
}
-
namespace DPL {
namespace Test {
-void TestRunner::RegisterTest(const char *testName, TestCase proc)
+TestResult::FailStatus TryCatch(const std::function<void(void)> &func, std::string &reason) {
+ try {
+ func();
+ } catch (const DPL::Test::TestFailed &e) {
+ reason = e.GetMessage();
+ return TestResult::FailStatus::FAILED;
+ } catch (const DPL::Test::TestIgnored &e) {
+ reason = e.GetMessage();
+ return TestResult::FailStatus::IGNORED;
+ } catch (const std::exception &e) {
+ reason = e.what();
+ return TestResult::FailStatus::FAILED;
+ } catch (...) {
+ reason = "Unknown exception";
+ return TestResult::FailStatus::FAILED;
+ }
+ reason = std::string();
+ return TestResult::FailStatus::NONE;
+}
+
+void TestRunner::RegisterTest(TestCasePtr testCase)
{
- m_testGroups[m_currentGroup].push_back(TestCaseStruct(testName, proc));
+ m_testGroups[m_currentGroup].push_back(testCase);
+ m_testCaseSet.insert(testCase);
}
void TestRunner::InitGroup(const char* name)
{
if(!cit->second.empty())
{
- for(TestCaseStructList::const_iterator cj = cit->second.begin(); cj != cit->second.end(); ++cj)
+ for(TestCaseList::const_iterator cj = cit->second.begin(); cj != cit->second.end(); ++cj)
{
- std::string name = cj->name;
+ std::string name = (*cj)->GetName();
std::string::size_type st = name.find('_');
if(st != std::string::npos)
{
bool TestRunner::filterByXML(std::map<std::string, bool> & casesMap)
{
for (auto &group : m_testGroups) {
- TestCaseStructList newList;
+ TestCaseList newList;
for (auto &tc : group.second)
{
- if (casesMap.find(tc.name) != casesMap.end()) {
- casesMap[tc.name] = true;
+ if (casesMap.find(tc->GetName()) != casesMap.end()) {
+ casesMap[tc->GetName()] = true;
newList.push_back(tc);
}
}
return true;
}
-void TestRunner::RunTestCase(const TestCaseStruct& testCase)
+void TestRunner::RunTestCase(TestCasePtr testCase)
{
- setCurrentTestCase(&(const_cast<TestCaseStruct &>(testCase)));
- m_deferDeepness = 0U;
- try {
- testCase.proc();
- } catch (const TestFailed &e) {
- // Simple test failure
- CollectResult(testCase.name,
- TestResult(TestResult::FailStatus::FAILED,
- getConcatedFailReason(e.GetMessage())));
-
- setCurrentTestCase(nullptr);
- return;
- } catch (const TestIgnored &e) {
- if (m_runIgnored) {
- // Simple test have to be implemented
- CollectResult(testCase.name,
- TestResult(TestResult::FailStatus::IGNORED, e.GetMessage()));
- }
-
+ setCurrentTestCase(testCase);
+
+ std::string initReason;
+ TestResult::FailStatus initStatus = TryCatch(std::bind(&TestCase::Init, testCase),
+ initReason);
+ if (initStatus != TestResult::FailStatus::NONE) {
+ CollectResult(testCase->GetName(),
+ TestResult(initStatus, getConcatedFailReason(initReason), testCase->GetPerformance()));
setCurrentTestCase(nullptr);
return;
- } catch (const std::exception &) {
- // std exception failure
- CollectResult(testCase.name,
- TestResult(TestResult::FailStatus::FAILED, "std exception"));
+ }
- setCurrentTestCase(nullptr);
- return;
- } catch (...) {
- // Unknown exception failure
- CollectResult(testCase.name,
- TestResult(TestResult::FailStatus::FAILED, "unknown exception"));
- setCurrentTestCase(nullptr);
- return;
+ std::string testReason;
+ TestResult::FailStatus testStatus = TryCatch(std::bind(&TestCase::Test, testCase),
+ testReason);
+ testReason = getConcatedFailReason(testReason);
+ std::string finishReason;
+ TestResult::FailStatus finishStatus = TryCatch(std::bind(&TestCase::Finish, testCase),
+ finishReason);
+ finishReason = getConcatedFailReason(finishReason);
+
+ switch (finishStatus) {
+ case TestResult::FailStatus::FAILED:
+ testStatus = TestResult::FailStatus::FAILED;
+ if (!testReason.empty())
+ testReason += "\n";
+ testReason += finishReason;
+ break;
+ case TestResult::FailStatus::IGNORED:
+ if (testStatus == TestResult::FailStatus::NONE)
+ testStatus = TestResult::FailStatus::IGNORED;
+ if (!testReason.empty())
+ testReason += "\n";
+ testReason += finishReason;
+ case TestResult::FailStatus::NONE:
+ break;
+ default:
+ Assert(false && "Unhandled fail status");
}
- // Everything OK
- CollectResult(testCase.name,
- TestResult(TestResult::FailStatus::NONE,
- std::string(),
- testCase.performance));
+ CollectResult(testCase->GetName(),
+ TestResult(testStatus, testReason, testCase->GetPerformance()));
setCurrentTestCase(nullptr);
}
fprintf(stderr, "%sFound %d testcases...%s\n", GREEN_BEGIN, count, GREEN_END);
fprintf(stderr, "%s%s%s\n", GREEN_BEGIN, "Running tests...", GREEN_END);
for (auto &group : m_testGroups) {
- TestCaseStructList list = group.second;
+ TestCaseList list = group.second;
if (!list.empty()) {
for (auto &collector : m_collectors) {
collector.second->CollectCurrentTestGroupName(group.first);
}
list.sort();
- for (TestCaseStructList::const_iterator iterator = list.begin();
+ for (TestCaseList::const_iterator iterator = list.begin();
iterator != list.end();
++iterator)
{
- TestCaseStruct test = *iterator;
- if (m_startTestId == test.name) {
+ TestCasePtr test = *iterator;
+ if (m_startTestId == test->GetName()) {
m_startTestId = "";
}
fprintf(stderr, "%s%s%s\n\n", GREEN_BEGIN, "Finished", GREEN_END);
}
-TestRunner::TestCaseStruct *TestRunner::getCurrentTestCase()
+TestCasePtr TestRunner::getCurrentTestCase()
{
return m_currentTestCase;
}
-void TestRunner::setCurrentTestCase(TestCaseStruct* testCase)
+void TestRunner::setCurrentTestCase(TestCasePtr testCase)
{
m_currentTestCase = testCase;
}
void TestRunner::beginPerformance(std::chrono::system_clock::duration maxDurationInMicroseconds)
{
- TestCaseStruct* testCase = getCurrentTestCase();
+ TestCasePtr testCase = getCurrentTestCase();
if (!testCase)
return;
- if (!testCase->performance)
- testCase->performance.reset(new PerformanceResult(maxDurationInMicroseconds));
+ if (!testCase->GetPerformance())
+ testCase->SetPerformance(
+ std::unique_ptr<PerformanceResult> \
+ (new PerformanceResult(maxDurationInMicroseconds)));
}
void TestRunner::endPerformance()
{
- TestCaseStruct* testCase = getCurrentTestCase();
+ TestCasePtr testCase = getCurrentTestCase();
if (!testCase)
return;
- testCase->performance->Finish();
+ testCase->GetPerformance()->Finish();
}
ConstPerformanceResultPtr TestRunner::getCurrentTestCasePerformanceResult()
{
- TestCaseStruct* testCase = getCurrentTestCase();
+ TestCasePtr testCase = getCurrentTestCase();
if (!testCase)
return nullptr;
- return testCase->performance;
+ return testCase->GetPerformance();
}
void TestRunner::setCurrentTestCasePerformanceResult(const PerformanceResultPtr &performance)
{
- TestCaseStruct* testCase = getCurrentTestCase();
+ TestCasePtr testCase = getCurrentTestCase();
if (!testCase)
return;
- testCase->performance = performance;
+ testCase->SetPerformance(performance);
}
void TestRunner::addFailReason(const std::string &reason)
return reason + ret;
}
+TestRunner::~TestRunner()
+{
+ for(auto &t : m_testCaseSet)
+ delete t;
+}
+
void TestRunner::CollectResult(const std::string& id, const TestResult& result)
{
+ if (result.GetFailStatus() == TestResult::FailStatus::IGNORED && m_runIgnored)
+ return;
+
std::for_each(m_collectors.begin(),
m_collectors.end(),
[&](const TestResultsCollectors::value_type & collector)
arg.erase(0, startCmd.length());
for (auto &group : m_testGroups) {
for (auto &tc : group.second) {
- if (tc.name == arg) {
+ if (tc->GetName() == arg) {
m_startTestId = arg;
break;
}
TestCaseGroupMap::iterator found = m_testGroups.find(arg);
if (found != m_testGroups.end()) {
std::string name = found->first;
- TestCaseStructList newList = found->second;
+ TestCaseList newList = found->second;
m_testGroups.clear();
m_testGroups[name] = newList;
} else {
} else if (arg.find(listInGroup) == 0) {
arg.erase(0, listInGroup.length());
for (auto &test : m_testGroups[arg]) {
- printf("ID:%s\n", test.name.c_str());
+ printf("ID:%s\n", test->GetName().c_str());
}
return 0;
} else if (arg.find(allowChildLogs) == 0) {
pcrecpp::RE re(arg.c_str());
for (auto &group : m_testGroups) {
- TestCaseStructList newList;
+ TestCaseList newList;
for (auto &tc : group.second)
{
- if (re.PartialMatch(tc.name)) {
+ if (re.PartialMatch(tc->GetName())) {
newList.push_back(tc);
}
}
{
for (auto &group : m_testGroups) {
for (auto &tc : group.second) {
- printf("ID:%s:%s\n", group.first.c_str(), tc.name.c_str());
+ printf("ID:%s:%s\n", group.first.c_str(), tc->GetName().c_str());
}
}
return 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>
return SUCCESS;
}
-void RunChildProc(TestRunner::TestCase procChild)
+void RunChildProc(const std::function<void(void)> &testFunc)
{
PipeWrapper pipe;
if (!pipe.isReady()) {
// End Runner after current test
TestRunnerSingleton::Instance().Terminate();
- int code = CHILD_TEST_PASS;
- std::string msg;
-
bool allowLogs = TestRunnerSingleton::Instance().GetAllowChildLogs();
close(STDIN_FILENO);
pipe.setUsage(PipeWrapper::WRITEONLY);
- try {
- procChild();
- } catch (const DPL::Test::TestFailed &e) {
- msg = e.GetMessage();
- code = CHILD_TEST_FAIL;
- } catch (const DPL::Test::TestIgnored &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) {
*/
#include <sys/file.h>
+#include <dpl/assert.h>
#include <dpl/exception.h>
#include <dpl/test/test_failed.h>
#include <dpl/test/test_ignored.h>
return ERROR;
}
-void RunMultiProc(TestRunner::TestCase procMulti)
+void RunMultiProc(const std::function<void(void)> &testFunc)
{
SimplePipeWrapper pipe;
- int code = MULTI_TEST_PASS;
- std::string msg = "";
int pipeReturn;
int waitStatus;
}
// pipe
- try {
- procMulti();
- } catch (const TestFailed &e) {
- code = MULTI_TEST_FAILED;
- msg = e.GetMessage();
- } catch (const TestIgnored &e) {
- code = MULTI_TEST_IGNORED;
- msg = e.GetMessage();
- } catch (const std::exception &) {
- code = MULTI_TEST_FAILED;
- msg = "std exception";
- } catch (...) {
- // Unknown exception failure
- code = MULTI_TEST_FAILED;
- msg = "unknown exception";
+ int code;
+ std::string msg;
+ switch (TryCatch(testFunc, msg)) {
+ case TestResult::FailStatus::FAILED:
+ code = MULTI_TEST_FAILED;
+ break;
+ case TestResult::FailStatus::IGNORED:
+ code = MULTI_TEST_IGNORED;
+ break;
+ case TestResult::FailStatus::NONE:
+ code = MULTI_TEST_PASS;
+ break;
+ default:
+ Assert(false && "Unhandled fail status");
}
while (true) {