tizen 2.4 release
[framework/web/wrt-commons.git] / modules / test / include / dpl / test / test_runner.h
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 /*
17  * @file        test_runner.h
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @author      Lukasz Wrzosek (l.wrzosek@samsung.com)
20  * @version     1.0
21  * @brief       This file is the header file of test runner
22  */
23 #ifndef DPL_TEST_RUNNER_H
24 #define DPL_TEST_RUNNER_H
25
26 #include <dpl/singleton.h>
27 #include <dpl/availability.h>
28 #include <dpl/test/test_results_collector.h>
29
30 #include <atomic>
31 #include <sstream>
32 #include <string>
33 #include <vector>
34 #include <list>
35 #include <set>
36 #include <map>
37
38 namespace DPL {
39 namespace Test {
40 class TestRunner
41 {
42     typedef std::map<std::string, TestResultsCollectorBasePtr>
43     TestResultsCollectors;
44     TestResultsCollectors m_collectors;
45
46     std::string m_startTestId;
47     bool m_runIgnored;
48
49   public:
50     TestRunner()
51         : m_runIgnored(false)
52         , m_allowChildLogs(false)
53         , m_terminate(false)
54         , m_totalAssertions(0)
55     {}
56
57     typedef void (*TestCase)();
58
59   private:
60     struct TestCaseStruct
61     {
62         std::string name;
63         TestCase proc;
64
65         bool operator <(const TestCaseStruct &other) const
66         {
67             return name < other.name;
68         }
69
70         bool operator ==(const TestCaseStruct &other) const
71         {
72             return name == other.name;
73         }
74
75         TestCaseStruct(const std::string &n, TestCase p) :
76             name(n),
77             proc(p)
78         {}
79     };
80
81     typedef std::list<TestCaseStruct> TestCaseStructList;
82     typedef std::map<std::string, TestCaseStructList> TestCaseGroupMap;
83     TestCaseGroupMap m_testGroups;
84
85     typedef std::set<std::string> SelectedTestNameSet;
86     SelectedTestNameSet m_selectedTestNamesSet;
87     typedef std::set<std::string> SelectedTestGroupSet;
88     SelectedTestGroupSet m_selectedTestGroupSet;
89     std::string m_currentGroup;
90
91     // Terminate without any logs.
92     // Some test requires to call fork function.
93     // Child process must not produce any logs and should die quietly.
94     bool m_allowChildLogs;
95     bool m_terminate;
96
97     std::atomic<int> m_totalAssertions;
98
99     void Banner();
100     void InvalidArgs(const std::string& message = "Invalid arguments!");
101     void Usage();
102
103     bool filterGroupsByXmls(const std::vector<std::string> & files);
104     bool filterByXML(std::map<std::string, bool> & casesMap);
105     void normalizeXMLTag(std::string& str, const std::string& testcase);
106
107     enum Status { FAILED, IGNORED, PASS };
108
109     Status RunTestCase(const TestCaseStruct& testCase);
110
111     void RunTests();
112
113     void CollectResult(const std::string& id,
114                        const std::string& description,
115                        const TestResultsCollectorBase::FailStatus::Type status
116                            = TestResultsCollectorBase::FailStatus::NONE,
117                        const std::string& reason = std::string());
118
119   public:
120     class TestFailed
121     {
122       private:
123         std::string m_message;
124
125       public:
126         TestFailed()
127         {}
128
129         //! \brief Failed test message creator
130         //!
131         //! \param[in] aTest string for tested expression
132         //! \param[in] aFile source file name
133         //! \param[in] aLine source file line
134         //! \param[in] aMessage error message
135         TestFailed(const char* aTest,
136                    const char* aFile,
137                    int aLine,
138                    const std::string &aMessage);
139
140         TestFailed(const std::string &message);
141
142         std::string GetMessage() const
143         {
144             return m_message;
145         }
146     };
147
148     class Ignored
149     {
150       private:
151         std::string m_message;
152
153       public:
154         Ignored()
155         {}
156
157         Ignored(const std::string &message) :
158             m_message(message)
159         {}
160
161         std::string GetMessage() const
162         {
163             return m_message;
164         }
165     };
166
167     void MarkAssertion();
168
169     void RegisterTest(const char *testName, TestCase proc);
170     void InitGroup(const char* name);
171
172     int ExecTestRunner(int argc, char *argv[]);
173     typedef std::vector<std::string> ArgsList;
174     int ExecTestRunner(const ArgsList& args);
175     bool getRunIgnored() const;
176     // The runner will terminate as soon as possible (after current test).
177     void Terminate();
178     bool GetAllowChildLogs();
179 };
180
181 typedef DPL::Singleton<TestRunner> TestRunnerSingleton;
182 }
183 } // namespace DPL
184
185 #define RUNNER_TEST_GROUP_INIT(GroupName)                                \
186     static int Static##GroupName##Init()                                 \
187     {                                                                    \
188         DPL::Test::TestRunnerSingleton::Instance().InitGroup(#GroupName);\
189         return 0;                                                        \
190     }                                                                    \
191     const int DPL_UNUSED Static##GroupName##InitVar =                    \
192         Static##GroupName##Init();
193
194 #define RUNNER_TEST(Proc)                                                \
195     void Proc();                                                         \
196     static int Static##Proc##Init()                                      \
197     {                                                                    \
198         DPL::Test::TestRunnerSingleton::Instance().RegisterTest(#Proc, &Proc); \
199         return 0;                                                        \
200     }                                                                    \
201     const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init();   \
202     void Proc()
203
204 #define RUNNER_ASSERT_MSG(test, message)                                      \
205     do                                                                        \
206     {                                                                         \
207         DPL::Test::TestRunnerSingleton::Instance().MarkAssertion();           \
208                                                                               \
209         if (!(test))                                                          \
210         {                                                                     \
211             std::ostringstream assertMsg;                                     \
212             assertMsg << message;                                             \
213             throw DPL::Test::TestRunner::TestFailed(#test,                    \
214                                                     __FILE__,                 \
215                                                     __LINE__,                 \
216                                                     assertMsg.str());         \
217         }                                                                     \
218     } while (0)
219
220 #define RUNNER_ASSERT(test) RUNNER_ASSERT_MSG(test, "")
221
222 #define RUNNER_FAIL RUNNER_ASSERT(false)
223
224 #define RUNNER_IGNORED_MSG(message)                                           \
225     do {                                                                      \
226         std::ostringstream assertMsg;                                         \
227         assertMsg << message;                                                 \
228         throw DPL::Test::TestRunner::Ignored( assertMsg.str() );              \
229 } while (0)
230
231 #endif // DPL_TEST_RUNNER_H