Bridge++  Version 1.5.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
testManager.cpp
Go to the documentation of this file.
1 
14 #include "testManager.h"
15 
16 const std::string TestManager::class_name = "TestManager";
17 
18 
19 // prototype definition
20 std::vector<std::string> string_tokenize(const std::string& src, const char delim = '.');
21 
22 //====================================================================
23 int DoNothing()
24 {
25  return int();
26 }
27 
28 
29 //====================================================================
31 {
32  vout.general(m_vl, "\n");
33  vout.general(m_vl, "-------------------------------------------------\n");
34  vout.general(m_vl, "------------ <Bridge++ %s> Test Menu -----------\n", BRIDGE_VERSION);
35  vout.general(m_vl, "-------------------------------------------------\n");
36  vout.general(m_vl, "Please select test category name \n");
37 }
38 
39 
40 //====================================================================
42 {
43  if (!s_instance) {
44  //
45  // acquire lock here
46  //
47  if (!s_instance) {
49  }
50  //
51  // release lock here
52  //
53  }
54 
55  return *s_instance;
56 }
57 
58 
59 //====================================================================
61 {
62  static TestManager instance_;
63 
64  s_instance = &instance_;
65 }
66 
67 
68 //====================================================================
70  : m_vl(CommonParameters::Vlevel()),
71  m_root_node("<top_level>"),
72  m_precision(Test::default_precision)
73 {
74 }
75 
76 
77 //====================================================================
79 {
80  s_instance = 0;
81 }
82 
83 
84 //====================================================================
86 {
89  } else {
91  }
92 }
93 
94 
95 //====================================================================
97 {
98  menu(&m_root_node, true);
99 
100  std::string jobname = "<terminate>";
101  Communicator::broadcast(1, jobname, 0);
102 
103  vout.detailed(m_vl, "TestManager::interactive_master: rank=%d, exit.\n", Communicator::self());
104 }
105 
106 
107 //====================================================================
109 {
110  for ( ; ;) {
111  std::string jobname;
112  Communicator::broadcast(1, jobname, 0);
113 
114  vout.detailed(m_vl, "TestManager::interactive_slave: rank=%d, job=%s\n", Communicator::self(), jobname.c_str());
115 
116  if (jobname == "<terminate>") break;
117 
118  batch(jobname);
119  }
120 
121  vout.detailed(m_vl, "TestManager::interactive_slave: rank=%d, exit.\n", Communicator::self());
122 }
123 
124 
125 //====================================================================
126 void TestManager::batch(const std::string& arg)
127 {
129 
130  if (p && (p->m_function != DoNothing)) {
131  int result = p->m_function();
132  } else {
133  vout.general(m_vl, "%s: No such test is found: %s\n\n", class_name.c_str(), arg.c_str());
134  }
135 }
136 
137 
138 //====================================================================
139 void TestManager::batch_recursive(const std::string& arg)
140 {
141  vout.detailed(m_vl, "TestManager::batch_recursive: arg=\"%s\"\n", arg.c_str());
142 
143  if (Communicator::is_primary()) {
144  Node *p = (arg == "") ? &m_root_node : find_node(&m_root_node, string_tokenize(arg));
145 
146  if (p) {
147  m_stat.reset();
148 
149  run_traversal(p);
150 
151  stat_report();
152  } else {
153  vout.general(m_vl, "%s: No such test is found: %s\n\n", class_name.c_str(), arg.c_str());
154  }
155 
156  // send terminate signal to slave nodes
157  std::string jobname = "<terminate>";
158  Communicator::broadcast(1, jobname, 0);
159 
160  vout.detailed(m_vl, "TestManager::batch_recursive: rank=%d, exit.\n", Communicator::self());
161  } else {
163  }
164 }
165 
166 
167 //====================================================================
168 void TestManager::batch_recursive(const int argc, char **argv)
169 {
170  vout.detailed(m_vl, "TestManager::batch_recursive: argc=%d\n", argc);
171 
172  if (Communicator::is_primary()) {
173  m_stat.reset();
174 
175  for (int i = 0; i < argc; ++i) {
176  vout.detailed(m_vl, "TestManager::batch_recursive: argv[%d]=%s\n", i, argv[i]);
177 
178  std::string arg = std::string(argv[i]);
179 
180  Node *p = (arg == "") ? &m_root_node : find_node(&m_root_node, string_tokenize(arg));
181 
182  if (p) {
183  run_traversal(p);
184  } else {
185  vout.general(m_vl, "%s: No such test is found: %s\n\n", class_name.c_str(), arg.c_str());
186  }
187  }
188 
189  stat_report();
190 
191  // send terminate signal to slave nodes
192  std::string jobname = "<terminate>";
193  Communicator::broadcast(1, jobname, 0);
194 
195  vout.detailed(m_vl, "TestManager::batch_recursive: rank=%d, exit.\n", Communicator::self());
196  } else {
198  }
199 }
200 
201 
202 //====================================================================
203 bool TestManager::registerTest(const std::string& key, const Test_function func)
204 {
206  return true;
207 }
208 
209 
210 //====================================================================
211 void TestManager::run(const Node *p)
212 {
213  if (!p) return;
214 
215  if (p->m_function == DoNothing) return;
216 
217  std::string testname = find_fullpath(p);
218  vout.general(m_vl, "run test \"%s\"\n", testname.c_str());
219 
220  if (Communicator::is_primary()) {
221  Communicator::broadcast(1, testname, 0);
222  }
223 
224  int result = p->m_function();
225 
226  // increment stat counter
227  if (result == -1) {
228  m_stat.skip(testname);
229  } else if (result == 0) {
230  m_stat.success(testname);
231  } else {
232  m_stat.failure(testname);
233  }
234 
235  // check result
236  //check_result(testname, result);
237 }
238 
239 
240 //====================================================================
242 {
243  if (!p) return;
244 
245  if (p->m_next.size() == 0) {
246  run(p);
247  } else {
248  for (size_t i = 0; i < p->m_next.size(); ++i) {
249  run_traversal(p->m_next[i]);
250  }
251  }
252 }
253 
254 
255 //====================================================================
256 bool TestManager::menu(const Node *p, bool is_top)
257 {
258  if (!p) return false;
259 
260  if (is_top && (p->m_next.size() > 0)) banner();
261 
262 
263  if (p->m_next.size() == 0) { // leaf node
264  vout.general(m_vl, "run %s\n", p->m_name.c_str());
265  run(p);
266  return true;
267  }
268 
269  bool do_continue = true;
270 
271  while (do_continue) // loop forever
272 
273  { // show item list
274  for (unsigned int i = 0; i < p->m_next.size(); ++i) {
275  vout.general(m_vl, "%u : %s\n", i + 1, p->m_next[i]->m_name.c_str());
276  }
277 
278  vout.general(m_vl, "a : Test All \n");
279  vout.general(m_vl, "p : Setup test check precision (current precision: %d)\n", m_precision);
280  if (!is_top) {
281  vout.general(m_vl, "u : Go back \n");
282  }
283  vout.general(m_vl, "q : Quit \n");
284 
285  char buf[1024];
286  buf[0] = '\0';
287 
288  int choice = 0;
289 
290  bool do_alltest = false;
291  bool do_setprecision = false;
292 
293  while (true) // loop until get valid answer.
294  {
295  vout.general(m_vl, "choice> ");
296  // scanf("%1023s", buf);
297  std::cin >> buf;
298 
299  if (buf[0] == 0) return false; // ctrl-D to escape
300 
301  if (buf[0] == 'a') {
302  do_alltest = true;
303  break;
304  }
305 
306  if (buf[0] == 'p') {
307  do_setprecision = true;
308  break;
309  }
310 
311  if (!is_top) {
312  if (buf[0] == 'u') return true; // go up.
313  }
314  if (buf[0] == 'q') return false; // quit.
315 
316 
317  choice = atoi(buf);
318  buf[0] = '\0';
319 
320  if ((choice >= 1) && (choice <= int(p->m_next.size()))) break;
321  }
322 
323  if (do_alltest) {
324  m_stat.reset();
325 
326  run_traversal(p);
327 
328  stat_report();
329  } else if (do_setprecision) {
330  set_precision();
331  } else {
332  do_continue = menu(p->m_next[choice - 1]);
333  }
334 
335  if (!do_continue) break;
336  }
337 
338  return do_continue;
339 }
340 
341 
342 //====================================================================
344 {
345  vout.general(m_vl, "Please input test check precision \n");
346  vout.general(m_vl, "input number from 1 to 14 (default: 12)\n");
347 
348  char buf[1024];
349  buf[0] = '\0';
350 
351  vout.general(m_vl, "precision = ");
352  // scanf("%1023s", buf);
353  std::cin >> buf;
354 
355  int prec = atoi(buf);
356  if ((prec >= 1) && (prec <= 14)) {
357  m_precision = prec;
358 
359  vout.general(m_vl, "precision set to %d\n", m_precision);
360  } else {
361  vout.general(m_vl, "invalid value.\n");
362  }
363 }
364 
365 
366 //====================================================================
367 TestManager::Node *TestManager::find_node(TestManager::Node *p, const std::vector<std::string>& v)
368 {
369  if (!p) return 0;
370 
371  if (v.size() == 0) return p;
372 
373  for (std::vector<std::string>::const_iterator r = v.begin(); r != v.end(); ++r) {
374  bool is_found = false;
375  size_t i = 0;
376  for (i = 0; i < p->m_next.size(); ++i) {
377  if (p->m_next[i]->m_name == (*r)) {
378  is_found = true;
379  break;
380  }
381  }
382 
383  if (!is_found) return 0;
384 
385  p = p->m_next[i];
386  }
387 
388  return p;
389 }
390 
391 
392 //====================================================================
393 TestManager::Node *TestManager::append_key(TestManager::Node *p, const std::vector<std::string>& v)
394 {
395  if (!p) return 0;
396 
397  if (v.size() == 0) return p;
398 
399  for (std::vector<std::string>::const_iterator r = v.begin(); r != v.end(); ++r) {
400  bool is_found = false;
401  size_t i = 0;
402  for (i = 0; i < p->m_next.size(); ++i) {
403  if (p->m_next[i]->m_name == (*r)) {
404  is_found = true;
405  break;
406  }
407  }
408 
409  if (is_found) {
410  p = p->m_next[i];
411  } else {
412  Node *q = new Node(*r, p);
413 
414  //append at the end of list
415  // p->m_next.push_back(q);
416 
417  //append in alphabetical order
418  std::vector<Node *>::iterator iter = p->m_next.begin();
419  for ( ; iter != p->m_next.end(); ++iter) {
420  if (*r < (*iter)->m_name) {
421  break;
422  }
423  }
424  p->m_next.insert(iter, q);
425 
426  p = q;
427  }
428  }
429 
430  return p;
431 }
432 
433 
434 //====================================================================
436 {
437  if (!p) return 0;
438 
439  if (argc == 0) return p;
440 
441  vout.general(m_vl, "%s: p=%p, argc=%d, argv={ ", __func__, p, argc);
442  for (int i = 0; i < argc; ++i) {
443  vout.general(m_vl, "%s, ", argv[i]);
444  }
445  vout.general(m_vl, "}\n");
446 
447  for (size_t i = 0; i < p->m_next.size(); ++i) {
448  if (p->m_next[i]->m_name == argv[0]) {
449  return append_key(p->m_next[i], argc - 1, argv + 1);
450  }
451  }
452 
453  Node *q = new Node(argv[0], p);
454  p->m_next.push_back(q);
455 
456  return append_key(q, argc - 1, argv + 1);
457 }
458 
459 
460 //====================================================================
461 std::string TestManager::find_fullpath(const TestManager::Node *p, const std::string& path)
462 {
463  if (!p) return path;
464 
465  if (!p->m_prev) return path; // omit "<top_level>"
466 
467  if (path.length() > 0) {
468  return find_fullpath(p->m_prev, p->m_name + '.' + path);
469  } else {
470  return find_fullpath(p->m_prev, p->m_name);
471  }
472 }
473 
474 
475 //====================================================================
477 {
478  m_num_tests = 0;
479  m_num_success = 0;
480  m_num_failure = 0;
481  m_num_skip = 0;
482  m_list_failure.resize(0);
483  m_list_skip.resize(0);
484 }
485 
486 
487 //====================================================================
488 void TestManager::Stat::success(const std::string& test_name)
489 {
490  ++m_num_tests;
491  ++m_num_success;
492 }
493 
494 
495 //====================================================================
496 void TestManager::Stat::failure(const std::string& test_name)
497 {
498  ++m_num_tests;
499  ++m_num_failure;
500  m_list_failure.push_back(test_name);
501 }
502 
503 
504 //====================================================================
505 void TestManager::Stat::skip(const std::string& test_name)
506 {
507  ++m_num_tests;
508  ++m_num_skip;
509  m_list_skip.push_back(test_name);
510 }
511 
512 
513 //====================================================================
515 {
516  vout.general(m_vl, "Test report:\n");
517  vout.general(m_vl, " Total number of tests = %3d\n", m_stat.m_num_tests);
518  vout.general(m_vl, " Number of successes = %3d\n", m_stat.m_num_success);
519  vout.general(m_vl, " Number of failures = %3d\n", m_stat.m_num_failure);
520  vout.general(m_vl, " Number of skipped = %3d\n", m_stat.m_num_skip);
521 
522  if (m_stat.m_num_failure > 0) {
523  vout.general(m_vl, " Failed tests:\n");
524  for (std::vector<std::string>::const_iterator p = m_stat.m_list_failure.begin(); p != m_stat.m_list_failure.end(); ++p) {
525  vout.general(m_vl, " %s\n", p->c_str());
526  }
527  }
528 
529 // if (m_stat.m_num_skip > 0) {
530 // vout.general(m_vl, " Skipped tests:\n");
531 // for (std::vector<std::string>::const_iterator p = m_stat.m_list_skip.begin(); p != m_stat.m_list_skip.end(); ++p) {
532 // vout.general(m_vl, " %s\n", p->c_str());
533 // }
534 // }
535 
536  if (m_stat.m_num_tests == 0) {
537  vout.general(m_vl, " No test is performed.\n");
538  } else {
539  if (m_stat.m_num_failure == 0) {
540  vout.general(m_vl, " All tests are performed successfully.\n");
541  }
542  }
543 
544  vout.general(m_vl, "\n");
545 }
546 
547 
548 //====================================================================
549 void TestManager::list_traverse(const Node *p, const string& prefix)
550 {
551  if (!p) return;
552 
553  if (p->m_next.size() == 0) {
554  if (prefix == "") {
555  vout.general(m_vl, "%s\n", p->m_name.c_str());
556  } else {
557  vout.general(m_vl, "%s.%s\n", prefix.c_str(), p->m_name.c_str());
558  }
559  return;
560  }
561 
562  string prefix_next = "";
563 
564  if (p == &m_root_node) {
565  } else if (prefix == "") {
566  prefix_next = p->m_name;
567  } else {
568  prefix_next = prefix + "." + p->m_name;
569  }
570 
571  for (size_t i = 0; i < p->m_next.size(); ++i) {
572  list_traverse(p->m_next[i], prefix_next);
573  }
574 }
575 
576 
577 //====================================================================
579 {
581 }
582 
583 
584 //====================================================================
585 void TestManager::traverse(const Node *p, const std::string& indent)
586 {
587  if (!p) return;
588 
589  if (p->m_next.size() == 0) {
590  vout.general(m_vl, "%sleaf \"%s\"\n", indent.c_str(), p->m_name.c_str());
591  return;
592  }
593 
594  vout.general(m_vl, "%snode \"%s\"\n", indent.c_str(), p->m_name.c_str());
595 
596  for (size_t i = 0; i < p->m_next.size(); ++i) {
597  traverse(p->m_next[i], indent + " ");
598  }
599 }
600 
601 
602 //====================================================================
603 std::vector<std::string> string_tokenize(const std::string& src, const char delim)
604 {
605  std::vector<std::string> retv;
606 
607  size_t npos = src.length();
608  size_t p = 0;
609 
610  while (true)
611  {
612  size_t q = src.find(delim, p);
613 
614  if (q >= npos) { // not found
615  retv.push_back(src.substr(p)); // append rest
616  break;
617  }
618 
619  retv.push_back(src.substr(p, q - p));
620  p = q + 1; // skip delimiter.
621  }
622 
623  return retv;
624 }
625 
626 
627 //====================================================================
629 
630 //====================================================================
631 //==============================================================END===
TestManager class for managing and performing tests.
Definition: testManager.h:52
BridgeIO vout
Definition: bridgeIO.cpp:503
int DoNothing()
Definition: testManager.cpp:23
void detailed(const char *format,...)
Definition: bridgeIO.cpp:216
static int self()
rank within small world.
#define BRIDGE_VERSION
Definition: configure.h:17
bool menu(const Node *p, const bool is_top=false)
void success(const std::string &test_name)
void general(const char *format,...)
Definition: bridgeIO.cpp:197
const std::string test_name
static void CreateInstance()
Definition: testManager.cpp:60
void run_traversal(const Node *p)
void failure(const std::string &test_name)
void batch_recursive(const std::string &arg="")
void interactive_slave()
std::string find_fullpath(const Node *p, const std::string &path="")
void list_traverse(const Node *p, const std::string &prefix)
void stat_report() const
void skip(const std::string &test_name)
int(* Test_function)(void)
Definition: testManager.h:27
void interactive_master()
Definition: testManager.cpp:96
void traverse(const Node *p, const std::string &indent="")
std::string m_name
Definition: testManager.h:94
void run(const Node *p)
std::vector< std::string > m_list_skip
Definition: testManager.h:117
Test_function m_function
Definition: testManager.h:95
Bridge::VerboseLevel m_vl
Definition: testManager.h:146
std::vector< std::string > m_list_failure
Definition: testManager.h:116
Node m_root_node
Definition: testManager.h:148
Common parameter class: provides parameters as singleton.
static const int default_precision
Definition: test.h:32
static TestManager & Instance()
Definition: testManager.cpp:41
void interactive()
Definition: testManager.cpp:85
static TestManager * s_instance
Definition: testManager.h:87
Node * find_node(Node *p, const std::vector< std::string > &v)
static int broadcast(int count, double *data, int sender)
broadcast array of double from sender.
bool registerTest(const std::string &key, const Test_function func)
static bool is_primary()
check if the present node is primary in small communicator.
std::vector< Node * > m_next
Definition: testManager.h:93
void banner()
Definition: testManager.cpp:30
std::vector< std::string > string_tokenize(const std::string &src, const char delim= '.')
static const std::string class_name
Definition: testManager.h:55
void set_precision()
Node * append_key(Node *p, const std::vector< std::string > &v)
void batch(const std::string &arg)