[Non-ACR][TFIVE-357]
[platform/core/system/sensord.git] / src / sensorctl / test_bench.cpp
1 /*
2  * sensorctl
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include "test_bench.h"
21
22 #include <getopt.h>
23 #include <regex>
24
25 #include "log.h"
26
27 /*
28  * Implementation of test_option
29  */
30 bool test_option::verbose = false;
31 bool test_option::shuffle = false;
32 bool test_option::show_list = false;
33 int test_option::repeat = 1;
34 std::string test_option::filter = "";
35 std::string test_option::output = "";
36 int test_option::interval = -1;
37 int test_option::latency = -1;
38 int test_option::powersave = -1;
39
40 bool test_option::set_options(int argc, char *argv[])
41 {
42         int c;
43
44         while (1) {
45                 static struct option options[] = {
46                         {"list", no_argument, 0, 'l'},
47                         {"filter", required_argument, 0, 'f'},
48                         {"verbose", no_argument, 0, 'v'},
49                         {"shuffle", no_argument, 0, 's'},
50                         {"repeat", required_argument, 0, 'r'},
51                         {"output", required_argument, 0, 'o'},
52
53                         /* For manual test*/
54                         {"interval", required_argument, 0, 'i'},
55                         {"batch_latency", required_argument, 0, 'b'},
56                         {"powersave", required_argument, 0, 'p'},
57
58                         {"help", no_argument, 0, 'h'},
59                         {0, 0, 0, 0}
60                 };
61
62                 int option_index = 0;
63                 c = getopt_long(argc, argv, "lfvsroibph:", options, &option_index);
64                 if (c == -1)
65                         return true;
66
67                 switch (c) {
68                 case 0:
69                         break;
70                 case 'l':
71                         _I("== Testcase List ==\n");
72                         test_bench::show_testcases();
73                         test_option::show_list = true;
74                         break;
75                 case 'f':
76                         _I("Filter : %s\n", optarg);
77                         if (!optarg) break;
78                         test_option::filter = optarg;
79                         break;
80                 case 'v':
81                         _I("Verbose is on\n");
82                         test_option::verbose = true;
83                         break;
84                 case 's':
85                         _I("Shuffle is on(Default seed)\n");
86                         test_option::shuffle = true;
87                         break;
88                 case 'r':
89                         _I("Repeat : %s\n", optarg);
90                         if (!optarg) break;
91                         test_option::repeat = atoi(optarg);
92                         break;
93                 case 'o':
94                         /* [TODO] */
95                         _W("File output is not supported yet, use $sensorctl > out : %s\n", optarg);
96                         if (!optarg) break;
97                         test_option::output = optarg;
98                         break;
99                 case 'i':
100                         _I("Interval : %s\n", optarg);
101                         if (!optarg) break;
102                         test_option::interval = atoi(optarg);
103                         break;
104                 case 'b':
105                         _I("Batch latency : %s\n", optarg);
106                         if (!optarg) break;
107                         test_option::latency = atoi(optarg);
108                         break;
109                 case 'p':
110                         _I("Power save : %s\n", optarg);
111                         if (!optarg) break;
112                         test_option::powersave = atoi(optarg);
113                         break;
114                 case 'h':
115                 case '?':
116                 default:
117                         return false;
118                 }
119         }
120
121         return true;
122 }
123
124 /*
125  * Implementation of test_case
126  */
127 test_case::test_case(const std::string &group, const std::string &name)
128 : m_group(group)
129 , m_name(name)
130 , m_fullname(group + "." + m_name)
131 , m_func(NULL)
132 {
133         test_bench::register_testcase(group, this);
134 }
135
136 void test_case::started(void)
137 {
138         _I("[ RUN      ] ");
139         _N("%s\n", m_fullname.c_str());
140 }
141
142 void test_case::stopped(bool result)
143 {
144         if (result)
145                 _I("[       OK ] ");
146         else
147                 _E("[  FAILED  ] ");
148         _N("%s\n", m_fullname.c_str());
149 }
150
151 void test_case::run_testcase(void)
152 {
153         bool result;
154
155         started();
156         result = (this->*m_func)();
157         stopped(result);
158 }
159
160 void test_case::register_func(test_func func)
161 {
162         m_func = func;
163 }
164
165 /*
166  * Implementation of test_bench
167  */
168 test_bench& test_bench::instance()
169 {
170         static test_bench bench;
171         return bench;
172 }
173
174 void test_bench::show_testcases(void)
175 {
176         instance().show();
177 }
178
179 void test_bench::register_testcase(const std::string &group, test_case *testcase)
180 {
181         instance().add_testcase(group, testcase);
182 }
183
184 void test_bench::push_failure(const std::string &function, long line, const std::string &msg)
185 {
186         instance().add_failure(function, line, msg);
187 }
188
189 void test_bench::run_all_testcases(void)
190 {
191         if (test_option::show_list)
192                 return;
193
194         instance().run();
195 }
196
197 void test_bench::stop_all_testcases(void)
198 {
199         instance().stop();
200 }
201
202 void test_bench::add_testcase(const std::string &group, test_case *testcase)
203 {
204         if (!testcase)
205                 return;
206
207         testcases.insert(std::pair<const std::string, test_case *>(group, testcase));
208 }
209
210 void test_bench::add_failure(const std::string &function, long line, const std::string &msg)
211 {
212         results.emplace_back(function, line, msg);
213         m_failure_count++;
214 }
215
216 void test_bench::started(void)
217 {
218         _I("[==========] ");
219         _N("Running %d testcase(s)\n", count());
220 }
221
222 void test_bench::stopped(void)
223 {
224         _I("[==========] ");
225         _N("%d testcase(s) ran\n", count());
226 }
227
228 void test_bench::show(void)
229 {
230         /*
231          * [group1]
232          *     [tc name1]
233          *     [tc name2]
234          * [group2]
235          *     [tc name1]
236          */
237
238         for (auto it = testcases.begin(); it != testcases.end();
239                         it = testcases.upper_bound(it->first)) {
240                 auto range = testcases.equal_range(it->first);
241                 _I("[%s]\n", it->first.c_str());
242
243                 for (auto testcase = range.first; testcase != range.second; ++testcase)
244                         _N("    * %s\n", testcase->second->name().c_str());
245         }
246
247         _I("Testcase Count : %u\n", count());
248 }
249
250 void test_bench::show_failures(void)
251 {
252         _N("================================\n");
253
254         if (m_failure_count == 0) {
255                 _I("[  PASSED  ] ");
256                 _N("%d tests\n", count() - m_failure_count);
257                 return;
258         }
259
260         _N("%d case(s) are failed, listed below:\n", m_failure_count);
261
262         for (unsigned int i = 0; i < results.size(); ++i) {
263                 _E("[  FAILED  ] ");
264                 _N("%s\n", results[i].msg.c_str());
265         }
266 }
267
268 bool test_bench::filter(const std::string &name, const std::string &filter_str)
269 {
270         try {
271                 std::regex filter(filter_str.c_str(), std::regex::optimize);
272                 if (!std::regex_match(name, filter))
273                         return false;
274         } catch (std::regex_error &e) {
275         }
276
277         return true;
278 }
279
280 bool test_bench::filter_name(const std::string &name)
281 {
282         std::size_t gindex = test_option::filter.find(".");
283         if (gindex == std::string::npos)
284                 return true;
285
286         std::size_t size = test_option::filter.size();
287         std::string filter_name = test_option::filter.substr(gindex + 1, size);
288
289         return filter(name, filter_name);
290 }
291
292 bool test_bench::filter_group(const std::string &group)
293 {
294         std::size_t gindex = test_option::filter.find(".");
295         if (gindex == std::string::npos)
296                 gindex = test_option::filter.size();
297
298         std::string filter_group = test_option::filter.substr(0, gindex);
299
300         return filter(group, filter_group);
301 }
302
303 void test_bench::run(void)
304 {
305         m_failure_count = 0;
306
307         started();
308
309         /* For group */
310         for (auto it = testcases.begin(); it != testcases.end();
311                         it = testcases.upper_bound(it->first)) {
312                 if (m_stop) break;
313                 if (!filter_group(it->second->group())) continue;
314
315                 auto range = testcases.equal_range(it->first);
316
317                 /* Time measurement for test group */
318                 clock_t start = clock();
319
320                 _I("[----------] %d tests from %s\n", testcases.count(it->first), it->first.c_str());
321                 for (auto testcase = range.first; testcase != range.second; ++testcase) {
322                         if (m_stop) break;
323                         if (!filter_name(testcase->second->name())) continue;
324
325                         testcase->second->run_testcase();
326                 }
327
328                 _I("[----------] %d tests from %s (%.4f sec)\n",
329                         testcases.count(it->first), it->first.c_str(),
330                         (double)(clock() - start)/ CLOCKS_PER_SEC);
331         }
332
333         stopped();
334         show_failures();
335 }
336
337 void test_bench::stop(void)
338 {
339         m_stop = true;
340 }
341
342 unsigned int test_bench::count(void)
343 {
344         static int count = -1;
345         if (count != -1)
346                 return count;
347
348         count = 0;
349         for (auto it = testcases.begin(); it != testcases.end(); ++it) {
350                 if (!filter_group(it->second->group()))
351                         continue;
352
353                 if (!filter_name(it->second->name()))
354                         continue;
355
356                 count++;
357         }
358
359         return count;
360 }