229 line
6.7 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. char const *GetName() { return "<UnitTestJob>"; }
  27. UnitTestJob() : ThreadJob(ThreadJobType::WORK_TODO)
  28. { }
  29. bool IsDone()
  30. {
  31. return m_done;
  32. }
  33. protected:
  34. virtual bool DoWork()
  35. {
  36. Timer timer;
  37. m_done = false;
  38. msg::info("%s: STARTED WORK\n", GetName());
  39. timer.Wait(2.f);
  40. msg::info("%s: ENDED WORK\n", GetName());
  41. m_done = true;
  42. return true;
  43. }
  44. bool m_done = false;
  45. };
  46. //Unit test thread manager
  47. class UnitTestThreadManager : public BaseThreadManager
  48. {
  49. typedef BaseThreadManager super;
  50. struct UnitTestStatusBase : public StructSafeEnum
  51. {
  52. enum Type
  53. {
  54. NOT_QUEUED,
  55. QUEUED,
  56. RETRIEVED,
  57. DONE,
  58. };
  59. protected:
  60. virtual bool BuildEnumMap(std::map<int64_t, std::string>& enum_map)
  61. {
  62. enum_map[NOT_QUEUED] = "NOT_QUEUED";
  63. enum_map[QUEUED] = "QUEUED";
  64. enum_map[RETRIEVED] = "RETRIEVED";
  65. enum_map[DONE] = "DONE";
  66. return true;
  67. }
  68. };
  69. typedef SafeEnum<UnitTestStatusBase> UnitTestStatus;
  70. public:
  71. char const *GetName() { return "<UnitTestThreadManager>"; }
  72. UnitTestThreadManager() : BaseThreadManager(4, 1)
  73. { }
  74. virtual ~UnitTestThreadManager()
  75. { }
  76. void AddJob(ThreadJob* job)
  77. {
  78. msg::info("%s DISPATCHING JOB %s\n", GetName(), job->GetName());
  79. DispatchJob(job);
  80. }
  81. bool GetWorkResult(array<ThreadJob*>& results)
  82. {
  83. results += m_job_result;
  84. m_job_result.empty();
  85. msg::info("%s GETWORKRESULT (%i)\n", GetName(), results.count());
  86. return results.count() > 0;
  87. }
  88. virtual void TickGame(float seconds)
  89. {
  90. switch (m_status.ToScalar())
  91. {
  92. case UnitTestStatus::NOT_QUEUED:
  93. if (!!GetDispatchCount())
  94. {
  95. msg::info("%s TICKGAME %s\n", GetName(), m_status.tostring().c_str());
  96. m_status = UnitTestStatus::QUEUED;
  97. }
  98. break;
  99. case UnitTestStatus::QUEUED:
  100. #if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
  101. if (!GetDispatchedCount())
  102. #else //LOL_FEATURE_THREADS
  103. if (GetDispatchedCount())
  104. #endif
  105. {
  106. msg::info("%s TICKGAME %s\n", GetName(), m_status.tostring().c_str());
  107. m_status = UnitTestStatus::RETRIEVED;
  108. }
  109. break;
  110. case UnitTestStatus::RETRIEVED:
  111. if (m_job_result.count() == 4)
  112. {
  113. msg::info("%s TICKGAME %s\n", GetName(), m_status.tostring().c_str());
  114. m_status = UnitTestStatus::DONE;
  115. }
  116. break;
  117. default:
  118. break;
  119. }
  120. //Debug error fix-up
  121. #if !LOL_BUILD_RELEASE
  122. m_tickstate = STATE_PRETICK_GAME;
  123. #endif
  124. super::TickGame(seconds);
  125. }
  126. bool IsDone() { return m_status == UnitTestStatus::DONE; }
  127. int Test_GetDispatchCount() { return GetDispatchCount(); }
  128. int Test_GetDispatchedCount() { return GetDispatchedCount(); }
  129. protected:
  130. virtual void TreatResult(ThreadJob* result) { m_job_result << result; }
  131. array<ThreadJob*> m_job_result;
  132. UnitTestStatus m_status;
  133. };
  134. UnitTestThreadManager m_manager;
  135. void setup()
  136. {
  137. }
  138. void teardown()
  139. {
  140. }
  141. lolunit_declare_test(threads)
  142. {
  143. msg::info("%s START\n", m_manager.GetName());
  144. //Start threads manager
  145. m_manager.Start();
  146. msg::info("%s STARTED\n", m_manager.GetName());
  147. UnitTestJob job[4];
  148. lolunit_assert_equal(0, m_manager.Test_GetDispatchCount());
  149. m_manager.AddJob(&job[0]);
  150. lolunit_assert_equal(1, m_manager.Test_GetDispatchCount());
  151. lolunit_assert_equal(false, job[0].IsDone());
  152. bool dispatch_check = true;
  153. while (!m_manager.IsDone())
  154. {
  155. m_manager.TickGame(1.f / 60.f);
  156. if (dispatch_check)
  157. {
  158. lolunit_assert_equal(0, m_manager.Test_GetDispatchCount());
  159. #if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
  160. lolunit_assert_equal(0, m_manager.Test_GetDispatchedCount());
  161. #else //LOL_FEATURE_THREADS
  162. lolunit_assert_equal(1, m_manager.Test_GetDispatchedCount());
  163. #endif
  164. m_manager.AddJob(&job[1]);
  165. m_manager.AddJob(&job[2]);
  166. m_manager.AddJob(&job[3]);
  167. dispatch_check = false;
  168. }
  169. }
  170. lolunit_assert_equal(true, job[0].IsDone());
  171. lolunit_assert_equal(true, job[1].IsDone());
  172. lolunit_assert_equal(true, job[2].IsDone());
  173. lolunit_assert_equal(true, job[3].IsDone());
  174. array<ThreadJob*> results;
  175. m_manager.GetWorkResult(results);
  176. lolunit_assert_equal(4, results.count());
  177. msg::info("%s STOP\n", m_manager.GetName());
  178. //Stop manager
  179. m_manager.Stop();
  180. msg::info("%s STOPPED\n", m_manager.GetName());
  181. }
  182. lolunit_declare_test(queue_try_push)
  183. {
  184. queue<int, 1> q;
  185. bool b1 = q.try_push(0);
  186. lolunit_assert_equal(true, b1);
  187. bool b2 = q.try_push(1);
  188. lolunit_assert_equal(false, b2);
  189. }
  190. lolunit_declare_test(queue_try_pop)
  191. {
  192. queue<int, 1> q;
  193. int tmp;
  194. q.push(42);
  195. bool b1 = q.try_pop(tmp);
  196. lolunit_assert_equal(true, b1);
  197. lolunit_assert_equal(42, tmp);
  198. bool b2 = q.try_pop(tmp);
  199. lolunit_assert_equal(false, b2);
  200. lolunit_assert_equal(42, tmp);
  201. }
  202. };
  203. } /* namespace lol */