Framework.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  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. #if ANKI_OS_ANDROID
  10. # include <android/log.h>
  11. #endif
  12. namespace anki
  13. {
  14. #if !ANKI_OS_ANDROID
  15. # define ANKI_TEST_LOG(fmt, ...) printf(fmt "\n", __VA_ARGS__)
  16. #else
  17. # define ANKI_TEST_LOG(fmt, ...) __android_log_print(ANDROID_LOG_INFO, "AnKi Tests", fmt, __VA_ARGS__)
  18. #endif
  19. TestSuite::~TestSuite()
  20. {
  21. for(Test* t : tests)
  22. {
  23. delete t;
  24. }
  25. }
  26. void Test::run()
  27. {
  28. ANKI_TEST_LOG("========\nRunning %s %s\n========", suite->name.c_str(), name.c_str());
  29. #if ANKI_OS_LINUX
  30. struct mallinfo a = mallinfo();
  31. #endif
  32. callback(*this);
  33. #if ANKI_OS_LINUX
  34. struct mallinfo b = mallinfo();
  35. int diff = b.uordblks - a.uordblks;
  36. if(diff > 0)
  37. {
  38. ANKI_TEST_LOG("Test leaks memory: %d", diff);
  39. }
  40. #endif
  41. }
  42. void Tester::addTest(const char* name, const char* suiteName, TestCallback callback)
  43. {
  44. std::vector<TestSuite*>::iterator it;
  45. for(it = suites.begin(); it != suites.end(); it++)
  46. {
  47. if((*it)->name == suiteName)
  48. {
  49. break;
  50. }
  51. }
  52. // Not found
  53. TestSuite* suite = nullptr;
  54. if(it == suites.end())
  55. {
  56. suite = new TestSuite;
  57. suite->name = suiteName;
  58. suites.push_back(suite);
  59. }
  60. else
  61. {
  62. suite = *it;
  63. }
  64. // Sanity check
  65. std::vector<Test*>::iterator it1;
  66. for(it1 = suite->tests.begin(); it1 != suite->tests.end(); it1++)
  67. {
  68. if((*it)->name == name)
  69. {
  70. ANKI_TEST_LOG("Test already exists: %s", name);
  71. return;
  72. }
  73. }
  74. // Add the test
  75. Test* test = new Test;
  76. suite->tests.push_back(test);
  77. test->name = name;
  78. test->suite = suite;
  79. test->callback = callback;
  80. }
  81. int Tester::run(int argc, char** argv)
  82. {
  83. // Parse args
  84. //
  85. programName = argv[0];
  86. std::string helpMessage = "Usage: " + programName + R"( [options]
  87. Options:
  88. --help Print this message
  89. --list-tests List all the tests
  90. --suite <name> Run tests only from this suite
  91. --test <name> Run this test. --suite needs to be specified)";
  92. std::string suiteName;
  93. std::string testName;
  94. for(int i = 1; i < argc; i++)
  95. {
  96. const char* arg = argv[i];
  97. if(strcmp(arg, "--list-tests") == 0)
  98. {
  99. listTests();
  100. return 0;
  101. }
  102. else if(strcmp(arg, "--help") == 0)
  103. {
  104. ANKI_TEST_LOG("%s", helpMessage.c_str());
  105. return 0;
  106. }
  107. else if(strcmp(arg, "--suite") == 0)
  108. {
  109. ++i;
  110. if(i >= argc)
  111. {
  112. ANKI_TEST_LOG("%s", "<name> is missing after --suite");
  113. return 1;
  114. }
  115. suiteName = argv[i];
  116. }
  117. else if(strcmp(arg, "--test") == 0)
  118. {
  119. ++i;
  120. if(i >= argc)
  121. {
  122. ANKI_TEST_LOG("%s", "<name> is missing after --test");
  123. return 1;
  124. }
  125. testName = argv[i];
  126. }
  127. }
  128. // Sanity check
  129. if(testName.length() > 0 && suiteName.length() == 0)
  130. {
  131. ANKI_TEST_LOG("%s", "Specify --suite as well");
  132. return 1;
  133. }
  134. // Run tests
  135. //
  136. int passed = 0;
  137. int run = 0;
  138. if(argc == 1)
  139. {
  140. // Run all
  141. for(TestSuite* suite : suites)
  142. {
  143. for(Test* test : suite->tests)
  144. {
  145. ++run;
  146. test->run();
  147. ++passed;
  148. }
  149. }
  150. }
  151. else
  152. {
  153. for(TestSuite* suite : suites)
  154. {
  155. if(suite->name == suiteName)
  156. {
  157. for(Test* test : suite->tests)
  158. {
  159. if(test->name == testName || testName.length() == 0)
  160. {
  161. ++run;
  162. test->run();
  163. ++passed;
  164. }
  165. }
  166. }
  167. }
  168. }
  169. int failed = run - passed;
  170. ANKI_TEST_LOG("========\nRun %d tests, failed %d", run, failed);
  171. if(failed == 0)
  172. {
  173. ANKI_TEST_LOG("%s", "SUCCESS!");
  174. }
  175. else
  176. {
  177. ANKI_TEST_LOG("%s", "FAILURE");
  178. }
  179. return run - passed;
  180. }
  181. int Tester::listTests()
  182. {
  183. for(TestSuite* suite : suites)
  184. {
  185. for(Test* test : suite->tests)
  186. {
  187. ANKI_TEST_LOG("%s --suite %s --test %s", programName.c_str(), suite->name.c_str(), test->name.c_str());
  188. }
  189. }
  190. return 0;
  191. }
  192. static Tester* g_testerInstance = nullptr;
  193. Tester& getTesterSingleton()
  194. {
  195. return *(g_testerInstance ? g_testerInstance : (g_testerInstance = new Tester));
  196. }
  197. void deleteTesterSingleton()
  198. {
  199. delete g_testerInstance;
  200. }
  201. void initConfig(ConfigSet& cfg)
  202. {
  203. cfg.set("width", 1920);
  204. cfg.set("height", 1080);
  205. cfg.set("rsrc_dataPaths", ".:..");
  206. }
  207. NativeWindow* createWindow(const ConfigSet& cfg)
  208. {
  209. HeapAllocator<U8> alloc(allocAligned, nullptr);
  210. NativeWindowInitInfo inf;
  211. inf.m_width = cfg.getNumberU32("width");
  212. inf.m_height = cfg.getNumberU32("height");
  213. inf.m_title = "AnKi unit tests";
  214. NativeWindow* win = new NativeWindow();
  215. ANKI_TEST_EXPECT_NO_ERR(win->init(inf, alloc));
  216. return win;
  217. }
  218. GrManager* createGrManager(const ConfigSet& cfg, NativeWindow* win)
  219. {
  220. GrManagerInitInfo inf;
  221. inf.m_allocCallback = allocAligned;
  222. inf.m_cacheDirectory = "./";
  223. inf.m_config = &cfg;
  224. inf.m_window = win;
  225. GrManager* gr;
  226. ANKI_TEST_EXPECT_NO_ERR(GrManager::newInstance(inf, gr));
  227. return gr;
  228. }
  229. ResourceManager* createResourceManager(const ConfigSet& cfg, GrManager* gr, PhysicsWorld*& physics,
  230. ResourceFilesystem*& resourceFs)
  231. {
  232. HeapAllocator<U8> alloc(allocAligned, nullptr);
  233. physics = new PhysicsWorld();
  234. ANKI_TEST_EXPECT_NO_ERR(physics->init(allocAligned, nullptr));
  235. resourceFs = new ResourceFilesystem(alloc);
  236. ANKI_TEST_EXPECT_NO_ERR(resourceFs->init(cfg, "./"));
  237. ResourceManagerInitInfo rinit;
  238. rinit.m_gr = gr;
  239. rinit.m_physics = physics;
  240. rinit.m_resourceFs = resourceFs;
  241. rinit.m_config = &cfg;
  242. rinit.m_cacheDir = "./";
  243. rinit.m_allocCallback = allocAligned;
  244. rinit.m_allocCallbackData = nullptr;
  245. ResourceManager* resources = new ResourceManager();
  246. ANKI_TEST_EXPECT_NO_ERR(resources->init(rinit));
  247. return resources;
  248. }
  249. } // end namespace anki