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