*
*/
-#include "log.h"
#include "test_bench.h"
+#include <getopt.h>
+#include <regex>
+
+#include "log.h"
+
/*
* Implementation of test_option
*/
-bool test_option::full_log = false;
-std::string test_option::group = "";
-
-void test_option::show_full_log(bool show)
+bool test_option::verbose = false;
+bool test_option::shuffle = false;
+bool test_option::show_list = false;
+int test_option::repeat = 1;
+std::string test_option::filter = "";
+std::string test_option::output = "";
+int test_option::interval = -1;
+int test_option::latency = -1;
+int test_option::powersave = -1;
+
+bool test_option::set_options(int argc, char *argv[])
{
- full_log = show;
-}
-
-void test_option::set_group(const char *gname)
-{
- group = gname;
-}
+ int c;
+
+ while (1) {
+ static struct option options[] = {
+ {"list", no_argument, 0, 'l'},
+ {"filter", required_argument, 0, 'f'},
+ {"verbose", no_argument, 0, 'v'},
+ {"shuffle", no_argument, 0, 's'},
+ {"repeat", required_argument, 0, 'r'},
+ {"output", required_argument, 0, 'o'},
+
+ /* For manual test*/
+ {"interval", required_argument, 0, 'i'},
+ {"batch_latency", required_argument, 0, 'b'},
+ {"powersave", required_argument, 0, 'p'},
+
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "lfvsroibph:", options, &option_index);
+ if (c == -1)
+ return true;
+
+ switch (c) {
+ case 0:
+ break;
+ case 'l':
+ _I("== Testcase List ==\n");
+ test_bench::show_testcases();
+ test_option::show_list = true;
+ break;
+ case 'f':
+ _I("Filter : %s\n", optarg);
+ if (!optarg) break;
+ test_option::filter = optarg;
+ break;
+ case 'v':
+ _I("Verbose is on\n");
+ test_option::verbose = true;
+ break;
+ case 's':
+ _I("Shuffle is on(Default seed)\n");
+ test_option::shuffle = true;
+ break;
+ case 'r':
+ _I("Repeat : %s\n", optarg);
+ if (!optarg) break;
+ test_option::repeat = atoi(optarg);
+ break;
+ case 'o':
+ /* [TODO] */
+ _W("File output is not supported yet, use $sensorctl > out : %s\n", optarg);
+ if (!optarg) break;
+ test_option::output = optarg;
+ break;
+ case 'i':
+ _I("Interval : %s\n", optarg);
+ if (!optarg) break;
+ test_option::interval = atoi(optarg);
+ break;
+ case 'b':
+ _I("Batch latency : %s\n", optarg);
+ if (!optarg) break;
+ test_option::latency = atoi(optarg);
+ break;
+ case 'p':
+ _I("Power save : %s\n", optarg);
+ if (!optarg) break;
+ test_option::powersave = atoi(optarg);
+ break;
+ case 'h':
+ case '?':
+ default:
+ return false;
+ }
+ }
-void test_option::set_options(int argc, char *argv[])
-{
- /* TODO: use getopt() */
- if (argc > 3)
- set_group(argv[3]);
- if (argc > 4)
- show_full_log(atoi(argv[4]));
+ return true;
}
/*
test_case::test_case(const std::string &group, const std::string &name)
: m_group(group)
, m_name(name)
+, m_fullname(group + "." + m_name)
, m_func(NULL)
{
test_bench::register_testcase(group, this);
void test_case::started(void)
{
- _I("[----------]\n");
_I("[ RUN ] ");
- _N("%s.%s\n", m_group.c_str(), m_name.c_str());
-}
-
-void test_case::stopped(void)
-{
- _I("[ OK ] ");
- _N("%s.%s\n", m_group.c_str(), m_name.c_str());
- _I("[----------]\n");
+ _N("%s\n", m_fullname.c_str());
}
-void test_case::show(bool result)
+void test_case::stopped(bool result)
{
if (result)
- _I("[ PASSED ] ");
+ _I("[ OK ] ");
else
_E("[ FAILED ] ");
- _N("%s.%s\n", m_group.c_str(), m_name.c_str());
+ _N("%s\n", m_fullname.c_str());
}
void test_case::run_testcase(void)
started();
result = (this->*m_func)();
- stopped();
- show(result);
+ stopped(result);
}
void test_case::register_func(test_func func)
return bench;
}
+void test_bench::show_testcases(void)
+{
+ instance().show();
+}
+
void test_bench::register_testcase(const std::string &group, test_case *testcase)
{
instance().add_testcase(group, testcase);
instance().add_failure(function, line, msg);
}
-void test_bench::run_all_testcase(void)
+void test_bench::run_all_testcases(void)
{
+ if (test_option::show_list)
+ return;
+
instance().run();
}
-void test_bench::stop_all_testcase(void)
+void test_bench::stop_all_testcases(void)
{
instance().stop();
}
void test_bench::started(void)
{
_I("[==========] ");
- _N("Running %d testcases\n", count(test_option::group));
+ _N("Running %d testcases\n", count());
}
void test_bench::stopped(void)
{
_I("[==========] ");
- _N("%d testcases ran\n", count(test_option::group));
+ _N("%d testcases ran\n", count());
+}
+
+void test_bench::show(void)
+{
+ /*
+ * [group1]
+ * [tc name1]
+ * [tc name2]
+ * [group2]
+ * [tc name1]
+ */
+
+ for (auto it = testcases.begin(); it != testcases.end();
+ it = testcases.upper_bound(it->first)) {
+
+ auto range = testcases.equal_range(it->first);
+ _I("[%s]\n", it->first.c_str());
+
+ for (auto testcase = range.first; testcase != range.second; ++testcase)
+ _N(" * %s\n", testcase->second->name().c_str());
+ }
+
+ _I("Testcase Count : %u\n", count());
}
void test_bench::show_failures(void)
_N("================================\n");
if (m_failure_count == 0) {
- _N("there was no fail case\n");
+ _I("[ PASSED ] ");
+ _N("%d tests\n", count() - m_failure_count);
return;
}
}
}
+bool test_bench::filter(const std::string &name)
+{
+ static std::regex filter(test_option::filter.c_str(), std::regex::optimize);
+ if (!std::regex_match(name, filter)) {
+ //_W("Not Matched : %s(%s)\n", name.c_str(), test_option::filter.c_str());
+ return false;
+ }
+
+ //_I("Matched : %s(%s)\n", name.c_str(), test_option::filter.c_str());
+ return true;
+}
+
void test_bench::run(void)
{
- std::size_t found;
m_failure_count = 0;
started();
- for (auto it = testcases.begin(); it != testcases.end(); ++it) {
- if (m_stop)
- break;
+ /* For group */
+ for (auto it = testcases.begin(); it != testcases.end();
+ it = testcases.upper_bound(it->first)) {
+ if (m_stop) break;
+ if (!filter(it->second->fullname())) continue;
- found = it->first.find("skip");
+ auto range = testcases.equal_range(it->first);
- if (test_option::group.empty() && found != std::string::npos)
- continue;
+ /* Time measurement for test group */
+ clock_t start = clock();
- found = it->first.find(test_option::group);
+ _I("[----------] %d tests from %s\n", testcases.count(it->first), it->first.c_str());
+ for (auto testcase = range.first; testcase != range.second; ++testcase) {
+ if (m_stop) break;
+ testcase->second->run_testcase();
+ }
- if (!test_option::group.empty() && found == std::string::npos)
- continue;
-
- it->second->run_testcase();
+ _I("[----------] %d tests from %s (%.4f sec)\n",
+ testcases.count(it->first), it->first.c_str(),
+ (double)(clock() - start)/ CLOCKS_PER_SEC);
}
stopped();
m_stop = true;
}
-unsigned int test_bench::count(std::string &group)
-{
- if (group.empty())
- return testcases.size() - count_by_key("skip");
-
- return count_by_key(group.c_str());
-}
-
-unsigned int test_bench::count_by_key(const char *key)
+unsigned int test_bench::count(void)
{
int count = 0;
for (auto it = testcases.begin(); it != testcases.end(); ++it) {
- std::size_t found = it->first.find(key);
+ if (!filter(it->second->fullname()))
+ continue;
- if (found != std::string::npos)
- count++;
+ count++;
}
return count;
#define PASS(left, comp, right) \
do { \
- if (test_option::full_log) { \
+ if (test_option::verbose) { \
_I("[ PASS ] "); \
std::ostringstream os; \
os << __FUNCTION__ << "(" << __LINE__ << ") : " \
} while (0)
#define TESTCASE(group, name) \
-class test_case_##group_##name : public test_case { \
+class test_case_##group##_##name : public test_case { \
public: \
- test_case_##group_##name() \
+ test_case_##group##_##name() \
: test_case(#group, #name) \
{ \
- register_func(static_cast<test_case::test_func>(&test_case_##group_##name::test)); \
+ register_func(static_cast<test_case::test_func>(&test_case_##group##_##name::test)); \
} \
bool test(void); \
-} test_case_##group_##name##_instance; \
-bool test_case_##group_##name::test(void)
+} test_case_##group##_##name##_instance; \
+bool test_case_##group##_##name::test(void)
/*
* Declaration of test_option
*/
class test_option {
public:
- static bool full_log;
- static std::string group;
-
- static void show_full_log(bool show);
- static void set_group(const char *gname);
- static void set_options(int argc, char *argv[]);
+ static bool verbose;
+ static bool shuffle; /* TODO */
+ static bool show_list;
+ static int repeat; /* TODO */
+ static std::string filter;
+ static std::string output; /* TODO */
+ static int interval;
+ static int latency;
+ static int powersave;
+
+ static bool set_options(int argc, char *argv[]);
};
/*
- * Decloaration of test_result
+ * Declaration of test_result
*/
class test_result {
public:
const std::string& group() const { return m_group; }
const std::string& name() const { return m_name; }
+ const std::string& fullname() const { return m_fullname; }
protected:
typedef bool (test_case::*test_func)();
void started(void);
- void stopped(void);
- void show(bool result);
+ void stopped(bool result);
void register_func(test_func func);
private:
const std::string m_group;
const std::string m_name;
+ const std::string m_fullname;
test_func m_func;
};
, m_stop(false)
{}
+ static void show_testcases(void);
+
static void register_testcase(const std::string &group, test_case *testcase);
- static void run_all_testcase(void);
- static void stop_all_testcase(void);
+ static void run_all_testcases(void);
+ static void stop_all_testcases(void);
static void push_failure(const std::string &function, long line, const std::string &msg);
void show_failures(void);
void add_testcase(const std::string &group, test_case *testcase);
+
+ bool filter(const std::string &name);
void run(void);
void stop(void);
- unsigned int count(std::string &group);
- unsigned int count_by_key(const char *key);
+ void show(void);
+
+ unsigned int count(void);
std::multimap<const std::string, test_case *> testcases;
std::vector<test_result> results;