Framework.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // Copyright (C) 2014, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include "tests/framework/Framework.h"
  6. #include <iostream>
  7. #include <cstring>
  8. #include <malloc.h>
  9. namespace anki {
  10. //==============================================================================
  11. TestSuite::~TestSuite()
  12. {
  13. for(Test* t : tests)
  14. {
  15. delete t;
  16. }
  17. }
  18. //==============================================================================
  19. void Test::run()
  20. {
  21. std::cout << "========\nRunning " << suite->name << " " << name
  22. << "\n========" << std::endl;
  23. struct mallinfo a = mallinfo();
  24. callback(*this);
  25. struct mallinfo b = mallinfo();
  26. int diff = b.uordblks - a.uordblks;
  27. if(diff > 0)
  28. {
  29. std::cerr << "Test leaks memory: " << diff << std::endl;
  30. }
  31. std::cout << std::endl;
  32. }
  33. //==============================================================================
  34. void Tester::addTest(const char* name, const char* suiteName,
  35. TestCallback callback)
  36. {
  37. std::vector<TestSuite*>::iterator it;
  38. for(it = suites.begin(); it != suites.end(); it++)
  39. {
  40. if((*it)->name == suiteName)
  41. {
  42. break;
  43. }
  44. }
  45. // Not found
  46. TestSuite* suite = nullptr;
  47. if(it == suites.end())
  48. {
  49. suite = new TestSuite;
  50. suite->name = suiteName;
  51. suites.push_back(suite);
  52. }
  53. else
  54. {
  55. suite = *it;
  56. }
  57. // Sanity check
  58. std::vector<Test*>::iterator it1;
  59. for(it1 = suite->tests.begin(); it1 != suite->tests.end(); it1++)
  60. {
  61. if((*it)->name == name)
  62. {
  63. std::cerr << "Test already exists: " << name << std::endl;
  64. return;
  65. }
  66. }
  67. // Add the test
  68. Test* test = new Test;
  69. suite->tests.push_back(test);
  70. test->name = name;
  71. test->suite = suite;
  72. test->callback = callback;
  73. }
  74. //==============================================================================
  75. int Tester::run(int argc, char** argv)
  76. {
  77. // Parse args
  78. //
  79. programName = argv[0];
  80. std::string helpMessage = "Usage: " + programName + R"( [options]
  81. Options:
  82. --help Print this message
  83. --list-tests List all the tests
  84. --suite <name> Run tests only from this suite
  85. --test <name> Run this test. --suite needs to be specified)";
  86. std::string suiteName;
  87. std::string testName;
  88. for(int i = 1; i < argc; i++)
  89. {
  90. const char* arg = argv[i];
  91. if(strcmp(arg, "--list-tests") == 0)
  92. {
  93. listTests();
  94. return 0;
  95. }
  96. else if(strcmp(arg, "--help") == 0)
  97. {
  98. std::cout << helpMessage << std::endl;
  99. return 0;
  100. }
  101. else if(strcmp(arg, "--suite") == 0)
  102. {
  103. ++i;
  104. if(i >= argc)
  105. {
  106. std::cerr << "<name> is missing after --suite" << std::endl;
  107. return 1;
  108. }
  109. suiteName = argv[i];
  110. }
  111. else if(strcmp(arg, "--test") == 0)
  112. {
  113. ++i;
  114. if(i >= argc)
  115. {
  116. std::cerr << "<name> is missing after --test" << std::endl;
  117. return 1;
  118. }
  119. testName = argv[i];
  120. }
  121. }
  122. // Sanity check
  123. if(testName.length() > 0 && suiteName.length() == 0)
  124. {
  125. std::cout << "Specify --suite as well" << std::endl;
  126. return 1;
  127. }
  128. // Run tests
  129. //
  130. int passed = 0;
  131. int run = 0;
  132. if(argc == 1)
  133. {
  134. // Run all
  135. for(TestSuite* suite : suites)
  136. {
  137. for(Test* test : suite->tests)
  138. {
  139. ++run;
  140. try
  141. {
  142. test->run();
  143. ++passed;
  144. }
  145. catch(const std::exception& e)
  146. {
  147. std::cerr << e.what() << std::endl;
  148. }
  149. }
  150. }
  151. }
  152. else
  153. {
  154. for(TestSuite* suite : suites)
  155. {
  156. if(suite->name == suiteName)
  157. {
  158. for(Test* test : suite->tests)
  159. {
  160. if(test->name == testName || testName.length() == 0)
  161. {
  162. ++run;
  163. try
  164. {
  165. test->run();
  166. ++passed;
  167. }
  168. catch(const std::exception& e)
  169. {
  170. std::cerr << e.what() << std::endl;
  171. }
  172. }
  173. }
  174. }
  175. }
  176. }
  177. int failed = run - passed;
  178. std::cout << "========\nRun " << run << " tests, failed " << failed
  179. << std::endl;
  180. if(failed == 0)
  181. {
  182. std::cout << "SUCCESS!" << std::endl;
  183. }
  184. else
  185. {
  186. std::cout << "FAILURE" << std::endl;
  187. }
  188. return run - passed;
  189. }
  190. //==============================================================================
  191. int Tester::listTests()
  192. {
  193. for(TestSuite* suite : suites)
  194. {
  195. for(Test* test : suite->tests)
  196. {
  197. std::cout << programName << " --suite \"" << suite->name
  198. << "\" --test \"" << test->name << "\"" << std::endl;
  199. }
  200. }
  201. return 0;
  202. }
  203. //==============================================================================
  204. static Tester* testerInstance = nullptr;
  205. Tester& getTesterSingleton()
  206. {
  207. return *(testerInstance ? testerInstance : (testerInstance = new Tester));
  208. }
  209. void deleteTesterSingleton()
  210. {
  211. if(testerInstance != nullptr)
  212. {
  213. delete testerInstance;
  214. }
  215. }
  216. } // end namespace anki