2 * Copyright (c) 2011-2017 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.
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19 * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
20 * @author Marcin Niesluchowski (m.niesluchow@samsung.com)
22 * @brief This file is the header file of test runner
25 #ifndef DPL_TEST_RUNNER_H
26 #define DPL_TEST_RUNNER_H
43 #include <dpl/atomic.h>
44 #include <dpl/availability.h>
45 #include <dpl/colors.h>
46 #include <dpl/gdbbacktrace.h>
47 #include <dpl/singleton.h>
48 #include <dpl/test/performance_result.h>
49 #include <dpl/test/test_group.h>
50 #include <dpl/test/test_case_extended.h>
51 #include <dpl/test/test_exception.h>
52 #include <dpl/test/test_failed.h>
53 #include <dpl/test/test_ignored.h>
54 #include <dpl/test/test_result.h>
55 #include <dpl/test/test_results_collector.h>
61 typedef std::map<std::string, TestResultsCollectorBasePtr>
62 TestResultsCollectors;
63 TestResultsCollectors m_collectors;
65 std::string m_startTestId;
68 std::queue<std::string> m_failReason;
72 m_currentTestCase(nullptr)
74 , m_allowChildLogs(false)
76 , m_firstDeferredExceptionType(DeferredExceptionType::DEFERRED_FAILED)
79 void beginPerformance(std::chrono::system_clock::duration maxDurationInMicroseconds);
80 void endPerformance();
81 void setCurrentTestCasePerformanceResult(const PerformanceResultPtr &performance);
82 ConstPerformanceResultPtr getCurrentTestCasePerformanceResult();
84 void addFailReason(const std::string &reason);
89 typedef std::map<std::string, TestGroup*> TestCaseGroupMap;
91 TestCaseGroupMap m_testGroups;
93 TestCasePtr m_currentTestCase;
95 TestGroupPtr m_currentGroup;
97 // Terminate without any logs.
98 // Some test requires to call fork function.
99 // Child process must not produce any logs and should die quietly.
101 bool m_allowChildLogs;
104 void InvalidArgs(const std::string& message = "Invalid arguments!");
107 bool filterGroupsByXmls(const std::vector<std::string> & files);
108 bool filterByXML(std::map<std::string, bool> & casesMap);
109 void normalizeXMLTag(std::string& str, const std::string& testcase);
111 void RunTestCase(TestCasePtr testCase);
113 void setCurrentTestCase(TestCasePtr testCase);
114 TestCasePtr getCurrentTestCase();
118 std::string getConcatedFailReason(const std::string &reason);
120 void CollectResult(const std::string& id, const TestResult &result);
123 void InitGroup(const char* name, TestGroup* group = nullptr);
124 void RegisterTest(TestCase* testCase);
125 int ExecTestRunner(int argc, char *argv[]);
126 typedef std::vector<std::string> ArgsList;
127 int ExecTestRunner(ArgsList args);
128 // The runner will terminate as soon as possible (after current test).
130 bool GetAllowChildLogs();
131 bool GetRunIgnored() const;
133 void deferFailedException(const DPL::Test::TestFailed &ex);
134 void deferIgnoredException(const DPL::Test::TestIgnored &ex);
139 std::vector<std::string> m_deferredExceptionsMessages;
140 std::size_t m_deferDeepness;
141 enum DeferredExceptionType {
144 } m_firstDeferredExceptionType;
145 DPL::Test::TestFailed m_firstDeferredFail;
146 DPL::Test::TestIgnored m_firstDeferredIgnore;
149 typedef DPL::Singleton<TestRunner> TestRunnerSingleton;
151 TestResult::FailStatus TryCatch(const std::function<void(void)> &func, std::string &reason);
154 * Test execution in multiple environments.
156 * To execute the same test in different environments provide an environment classes CLASS1, CLASS2,.... Classes have to
157 * provide init() & finish() methods to be called before and after execution in each environment.
158 * They should also provide suffix() method returning test case name suffix for given environment.
160 * Define the test as follows
162 * RUNNER_TEST_MULTIPLE(my_test, CLASS1, CLASS2,...)
164 * // do the test stuff
167 * For each class C the order of operation will be as follows:
168 * - construct C (default constructor)
169 * - call init() on C object
170 * - call test case function
171 * - call finish() on C object
172 * - destroy the C object
175 template <typename ...Args>
178 template <typename First>
179 struct StaticProc<First> {
181 static void Internal(const std::string& name, const TestFnType& proc) {
182 TestRunnerSingleton::Instance().RegisterTest(
183 new TestCaseExt2<First>(name + First::suffix(), proc));
187 template <typename First, typename ...Args>
188 struct StaticProc<First, Args...> : public StaticProc<First>, public StaticProc<Args...> {
189 static int Init(const std::string& name, const TestFnType& proc) {
190 StaticProc<First, Args...>::Internal(name, proc);
194 static void Internal(const std::string& name, const TestFnType& proc) {
195 StaticProc<First>::Internal(name, proc);
196 StaticProc<Args...>::Internal(name, proc);
203 #define RUNNER_TEST_GROUP_INIT_ENV(GroupName, GroupEnv) \
204 static int Static##GroupName##Init() \
206 DPL::Test::TestRunnerSingleton::Instance().InitGroup(#GroupName, new GroupEnv); \
209 const int DPL_UNUSED Static##GroupName##InitVar = \
210 Static##GroupName##Init();
212 #define RUNNER_TEST_GROUP_INIT(GroupName) \
213 static int Static##GroupName##Init() \
215 DPL::Test::TestRunnerSingleton::Instance().InitGroup(#GroupName); \
218 const int DPL_UNUSED Static##GroupName##InitVar = \
219 Static##GroupName##Init();
221 #define RUNNER_TEST(Proc, ...) \
222 void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple); \
223 static int Static##Proc##Init() \
225 DPL::Test::TestRunnerSingleton::Instance().RegisterTest( \
226 new DPL::Test::TestCaseExtended<__VA_ARGS__>(#Proc, &Proc)); \
229 const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
230 void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple DPL_UNUSED)
233 #define RUNNER_TEST_MULTIPLE(Proc, ...) \
235 const int DPL_UNUSED Static##Proc##InitVar = DPL::Test::StaticProc<__VA_ARGS__>::Init(#Proc, &Proc); \
241 * Use them to create assertions in test cases. To do that put them inside test
242 * body. Failing assertion indicates failing test.
245 #define RUNNER_ASSERT_MSG(test, message) \
250 std::ostringstream assertMsg; \
251 assertMsg << message << DPL::gdbbacktrace(); \
252 DPL::Test::TestFailed e(#test, \
260 #define RUNNER_ASSERT_ERRNO_MSG(test, message) \
265 const char *err = strerror(errno); \
266 std::ostringstream assertMsg; \
267 assertMsg << message; \
268 if (!assertMsg.str().empty()) \
270 assertMsg << err << DPL::gdbbacktrace(); \
271 DPL::Test::TestFailed e(#test, \
279 #define RUNNER_ASSERT_ERRNO(test) \
280 RUNNER_ASSERT_ERRNO_MSG(test, "")
282 #define RUNNER_FAIL_MSG(message) \
283 RUNNER_ASSERT_MSG(false, message)
285 #define RUNNER_ASSERT(test) \
286 RUNNER_ASSERT_MSG(test, "")
291 * When test reaches this macro call, its further code will be ignored.
292 * To ignore whole test, put this macro call at the beginning of this tests
296 #define RUNNER_IGNORED_MSG(message) \
299 if (DPL::Test::TestRunnerSingleton::Instance().GetRunIgnored()) { \
302 std::ostringstream assertMsg; \
303 assertMsg << message; \
304 throw DPL::Test::TestIgnored(assertMsg.str()); \
310 * Use these macros to do the time measurement. The first macro will start time measurement,
311 * the second will gather the result. These macros can be used only once per test-case.
312 * The result of time measurement will be displayed only if the test will pass.
313 * Notice that these macros will work only if will be used in parent process. If these
314 * macros will be used in child process then there will be no time measure results printed.
315 * This macro in multiprocess tests has effect only if used in parent process. This macro
316 * used in child process in multiprocess test has no effect.
317 * The precision of measurement is 1 microsecond - the smallest time value that can be
318 * measured is 0.000001s.
319 * The time measure results will be printed only specific output format:
325 #define RUNNER_PERF_TEST_BEGIN(maxTime) \
327 DPL::Test::TestRunnerSingleton::Instance().beginPerformance( \
328 std::chrono::microseconds{static_cast<long long int>(maxTime*1000000.0)}); \
331 #define RUNNER_PERF_TEST_END() \
333 DPL::Test::TestRunnerSingleton::Instance().endPerformance(); \
339 * Use these macros to print error messages during test run time
342 #define RUNNER_ERROR_MSG(message) \
344 std::cerr << DPL::Colors::Text::RED_BEGIN << message \
345 << DPL::Colors::Text::RED_END << std::endl; \
351 * Use them to defer fails and ignores in test cases.
352 * Some code constructions disallow to throw. Such places can be surrounded
353 * with RUNNER_DEFER_SCOPE macro. RUNNER_DEFER_TRYCATCH macro can be used to catch possibly thrown
354 * exceptions within such scope. Possibly catched exceptions will be rethrown
355 * when leaving RUNNER_DEFER_SCOPE scope.
356 * Macros can be safely nested.
360 #define RUNNER_DEFER_TRYCATCH(scope) \
366 catch (const DPL::Test::TestFailed &ex) \
368 DPL::Test::TestRunnerSingleton::Instance().deferFailedException(ex); \
370 catch (const DPL::Test::TestIgnored &ex) \
372 DPL::Test::TestRunnerSingleton::Instance().deferIgnoredException(ex); \
376 #define RUNNER_DEFER_SCOPE(scope) \
378 DPL::Test::TestRunnerSingleton::Instance().deferBegin(); \
380 DPL::Test::TestRunnerSingleton::Instance().deferEnd(); \
383 #endif // DPL_TEST_RUNNER_H