232 lines
6.8 KiB

  1. //
  2. // Lol Engine — Unit tests
  3. //
  4. // Copyright © 2010—2018 Sam Hocevar <sam@hocevar.net>
  5. // © 2014—2015 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
  6. //
  7. // Lol Engine is free software. It comes without any warranty, to
  8. // the extent permitted by applicable law. You can redistribute it
  9. // and/or modify it under the terms of the Do What the Fuck You Want
  10. // to Public License, Version 2, as published by the WTFPL Task Force.
  11. // See http://www.wtfpl.net/ for more details.
  12. //
  13. #include <lol/engine-internal.h>
  14. #include <string>
  15. #include <map>
  16. #include <lolunit.h>
  17. namespace lol
  18. {
  19. lolunit_declare_fixture(thread_test)
  20. {
  21. //FileUpdateTesterJob ---------------------------------------------------------
  22. class UnitTestJob : public ThreadJob
  23. {
  24. friend class UnitTestThreadManager;
  25. public:
  26. std::string GetName() const { return "<UnitTestJob>"; }
  27. UnitTestJob()
  28. : ThreadJob(ThreadJobType::WORK_TODO)
  29. { }
  30. bool IsDone()
  31. {
  32. return m_done;
  33. }
  34. protected:
  35. virtual bool DoWork()
  36. {
  37. timer t;
  38. m_done = false;
  39. msg::info("%s: STARTED WORK\n", GetName().c_str());
  40. t.wait(2.f);
  41. msg::info("%s: ENDED WORK\n", GetName().c_str());
  42. m_done = true;
  43. return true;
  44. }
  45. bool m_done = false;
  46. };
  47. //Unit test thread manager
  48. class UnitTestThreadManager : public BaseThreadManager
  49. {
  50. typedef BaseThreadManager super;
  51. struct UnitTestStatusBase : public StructSafeEnum
  52. {
  53. enum Type
  54. {
  55. NOT_QUEUED,
  56. QUEUED,
  57. RETRIEVED,
  58. DONE,
  59. };
  60. protected:
  61. virtual bool BuildEnumMap(std::map<int64_t, std::string>& enum_map)
  62. {
  63. enum_map[NOT_QUEUED] = "NOT_QUEUED";
  64. enum_map[QUEUED] = "QUEUED";
  65. enum_map[RETRIEVED] = "RETRIEVED";
  66. enum_map[DONE] = "DONE";
  67. return true;
  68. }
  69. };
  70. typedef SafeEnum<UnitTestStatusBase> UnitTestStatus;
  71. public:
  72. std::string GetName() const { return "<UnitTestThreadManager>"; }
  73. UnitTestThreadManager() : BaseThreadManager(4, 1)
  74. { }
  75. virtual ~UnitTestThreadManager()
  76. { }
  77. void AddJob(ThreadJob* job)
  78. {
  79. msg::info("%s DISPATCHING JOB %s\n", GetName().c_str(), job->GetName().c_str());
  80. DispatchJob(job);
  81. }
  82. bool GetWorkResult(array<ThreadJob*>& results)
  83. {
  84. results += m_job_result;
  85. m_job_result.empty();
  86. msg::info("%s GETWORKRESULT (%i)\n", GetName().c_str(), results.count());
  87. return results.count() > 0;
  88. }
  89. virtual void TickGame(float seconds)
  90. {
  91. switch (m_status.ToScalar())
  92. {
  93. case UnitTestStatus::NOT_QUEUED:
  94. if (!!GetDispatchCount())
  95. {
  96. msg::info("%s TICKGAME %s\n", GetName().c_str(), m_status.tostring().c_str());
  97. m_status = UnitTestStatus::QUEUED;
  98. }
  99. break;
  100. case UnitTestStatus::QUEUED:
  101. #if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
  102. if (!GetDispatchedCount())
  103. #else //LOL_FEATURE_THREADS
  104. if (GetDispatchedCount())
  105. #endif
  106. {
  107. msg::info("%s TICKGAME %s\n", GetName().c_str(), m_status.tostring().c_str());
  108. m_status = UnitTestStatus::RETRIEVED;
  109. }
  110. break;
  111. case UnitTestStatus::RETRIEVED:
  112. if (m_job_result.count() == 4)
  113. {
  114. msg::info("%s TICKGAME %s\n", GetName().c_str(), m_status.tostring().c_str());
  115. m_status = UnitTestStatus::DONE;
  116. }
  117. break;
  118. default:
  119. break;
  120. }
  121. //Debug error fix-up
  122. #if !LOL_BUILD_RELEASE
  123. m_tickstate = STATE_PRETICK_GAME;
  124. #endif
  125. super::TickGame(seconds);
  126. }
  127. bool IsDone() { return m_status == UnitTestStatus::DONE; }
  128. int Test_GetDispatchCount() { return GetDispatchCount(); }
  129. int Test_GetDispatchedCount() { return GetDispatchedCount(); }
  130. protected:
  131. virtual void TreatResult(ThreadJob* result) { m_job_result << result; }
  132. array<ThreadJob*> m_job_result;
  133. UnitTestStatus m_status;
  134. };
  135. UnitTestThreadManager m_manager;
  136. void setup()
  137. {
  138. }
  139. void teardown()
  140. {
  141. }
  142. lolunit_declare_test(threads)
  143. {
  144. msg::info("%s START\n", m_manager.GetName().c_str());
  145. //Start threads manager
  146. m_manager.Start();
  147. msg::info("%s STARTED\n", m_manager.GetName().c_str());
  148. UnitTestJob job[4];
  149. lolunit_assert_equal(0, m_manager.Test_GetDispatchCount());
  150. m_manager.AddJob(&job[0]);
  151. lolunit_assert_equal(1, m_manager.Test_GetDispatchCount());
  152. lolunit_assert_equal(false, job[0].IsDone());
  153. bool dispatch_check = true;
  154. while (!m_manager.IsDone())
  155. {
  156. m_manager.TickGame(1.f / 60.f);
  157. if (dispatch_check)
  158. {
  159. lolunit_assert_equal(0, m_manager.Test_GetDispatchCount());
  160. #if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
  161. lolunit_assert_equal(0, m_manager.Test_GetDispatchedCount());
  162. #else //LOL_FEATURE_THREADS
  163. lolunit_assert_equal(1, m_manager.Test_GetDispatchedCount());
  164. #endif
  165. m_manager.AddJob(&job[1]);
  166. m_manager.AddJob(&job[2]);
  167. m_manager.AddJob(&job[3]);
  168. dispatch_check = false;
  169. }
  170. }
  171. lolunit_assert_equal(true, job[0].IsDone());
  172. lolunit_assert_equal(true, job[1].IsDone());
  173. lolunit_assert_equal(true, job[2].IsDone());
  174. lolunit_assert_equal(true, job[3].IsDone());
  175. array<ThreadJob*> results;
  176. m_manager.GetWorkResult(results);
  177. lolunit_assert_equal(4, results.count());
  178. msg::info("%s STOP\n", m_manager.GetName().c_str());
  179. //Stop manager
  180. m_manager.Stop();
  181. msg::info("%s STOPPED\n", m_manager.GetName().c_str());
  182. }
  183. lolunit_declare_test(queue_try_push)
  184. {
  185. queue<int, 1> q;
  186. bool b1 = q.try_push(0);
  187. lolunit_assert_equal(true, b1);
  188. bool b2 = q.try_push(1);
  189. lolunit_assert_equal(false, b2);
  190. }
  191. lolunit_declare_test(queue_try_pop)
  192. {
  193. queue<int, 1> q;
  194. int tmp;
  195. q.push(42);
  196. bool b1 = q.try_pop(tmp);
  197. lolunit_assert_equal(true, b1);
  198. lolunit_assert_equal(42, tmp);
  199. bool b2 = q.try_pop(tmp);
  200. lolunit_assert_equal(false, b2);
  201. lolunit_assert_equal(42, tmp);
  202. }
  203. };
  204. } /* namespace lol */