testframework.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. enum TFR
  2. {
  3. FAIL = -1,
  4. SUCCESS,
  5. PENDING,
  6. }
  7. class TFResult // Pretty much just to be able to keep a reference...
  8. {
  9. TFR Result;
  10. void TFResult(TFR result)
  11. {
  12. Result = result;
  13. }
  14. TFResult And(TFResult other)
  15. {
  16. if (Result == TFR.PENDING || other.Result == TFR.PENDING)
  17. ErrorEx("Trying to And while one of the results are PENDING.");
  18. if (Result == TFR.SUCCESS && other.Result == TFR.SUCCESS)
  19. Result = TFR.SUCCESS;
  20. else
  21. Result = TFR.FAIL;
  22. return this;
  23. }
  24. TFResult Or(TFResult other)
  25. {
  26. if (Result == TFR.PENDING || other.Result == TFR.PENDING)
  27. ErrorEx("Trying to Or while one of the results are PENDING.");
  28. if (Result == TFR.SUCCESS || other.Result == TFR.SUCCESS)
  29. Result = TFR.SUCCESS;
  30. else
  31. Result = TFR.FAIL;
  32. return this;
  33. }
  34. }
  35. typedef array<ref TFResult> TFResultArr;
  36. class TFCaller
  37. {
  38. private Class m_Instance;
  39. private string m_Test;
  40. private ref TFResult m_Result;
  41. void TFCaller(Class instance, string test, TFResult result)
  42. {
  43. m_Instance = instance;
  44. m_Test = test;
  45. m_Result = result;
  46. }
  47. TFResult Run(float dt)
  48. {
  49. bool callResult = GetGame().GameScript.CallFunction(m_Instance, m_Test, m_Result, dt);
  50. if (!callResult)
  51. {
  52. ErrorEx(string.Format("Failed to call function \'%1\' on \'%2\'", m_Test, m_Instance.GetDebugName()));
  53. m_Result.Result = TFR.FAIL;
  54. }
  55. return m_Result;
  56. }
  57. string GetTest()
  58. {
  59. return m_Test;
  60. }
  61. string GetTestEx()
  62. {
  63. return string.Format("%1::%2", m_Instance.ClassName(), m_Test);
  64. }
  65. }
  66. typedef array<ref TFCaller> TFCallerArr;
  67. class TFModule
  68. {
  69. private int m_Count;
  70. private int m_Failed;
  71. private int m_Success;
  72. private ref TFCallerArr m_Tests;
  73. private ref TFResultArr m_Results;
  74. private ref array<string> m_SucceededTests;
  75. private ref array<string> m_FailedTests;
  76. void TFModule()
  77. {
  78. m_Tests = {};
  79. m_Results = {};
  80. m_SucceededTests = {};
  81. m_FailedTests = {};
  82. }
  83. int Count()
  84. {
  85. return m_Count;
  86. }
  87. int Failed()
  88. {
  89. return m_Failed;
  90. }
  91. int Success()
  92. {
  93. return m_Success;
  94. }
  95. int Pending()
  96. {
  97. return m_Count - (m_Failed + m_Success);
  98. }
  99. void AddTest(Class instance, string test, bool repeat)
  100. {
  101. ++m_Count;
  102. TFResult result = new TFResult(TFR.PENDING);
  103. m_Results.Insert(result);
  104. m_Tests.Insert(new TFCaller(instance, test, result));
  105. }
  106. bool Run(bool fatal, float dt)
  107. {
  108. array<TFCaller> done = new array<TFCaller>();
  109. // Run the tests
  110. int runningTests = m_Tests.Count();
  111. for (int i = 0; i < runningTests; ++i)
  112. {
  113. TFCaller t = m_Tests[i];
  114. if (RunTest(t, dt))
  115. done.Insert(t);
  116. }
  117. // Remove finished tests
  118. foreach (TFCaller doneT : done)
  119. m_Tests.RemoveItem(doneT);
  120. // Validate fatal
  121. if (fatal && m_Tests.Count() > 0)
  122. {
  123. Print("- Active tests -------------------------");
  124. foreach (TFCaller rTest : m_Tests)
  125. Print(rTest.GetTest());
  126. Print("----------------------------------------");
  127. ErrorEx("Not all tests are done while run was fatal.");
  128. m_Tests.Clear();
  129. }
  130. return m_Tests.Count() == 0;
  131. }
  132. private bool RunTest(TFCaller caller, float dt)
  133. {
  134. TFR res = caller.Run(dt).Result;
  135. switch (res)
  136. {
  137. case TFR.FAIL:
  138. ++m_Failed;
  139. m_FailedTests.Insert(caller.GetTestEx());
  140. break;
  141. case TFR.SUCCESS:
  142. ++m_Success;
  143. m_SucceededTests.Insert(caller.GetTestEx());
  144. break;
  145. }
  146. return res != TFR.PENDING;
  147. }
  148. string Result()
  149. {
  150. return string.Format("{ [TFModule] :: Tests: %1 | Success: %2 | Failed: %3 | Pending: %4 }", Count(), Success(), Failed(), Pending());
  151. }
  152. void PrintResult(string prefix = "", TestFramework caller = null, string function = "")
  153. {
  154. Debug.TFLog(string.Format("%1%2", prefix, Result()), caller, function);
  155. if (m_SucceededTests.Count())
  156. {
  157. Debug.TFLog(" |-[SUCCESS]", caller, function);
  158. foreach (string success : m_SucceededTests)
  159. {
  160. Debug.TFLog(string.Format(" |- %1", success), caller, function);
  161. }
  162. }
  163. if (m_FailedTests.Count())
  164. {
  165. Debug.TFLog(" |-[FAILED]", caller, function);
  166. foreach (string fail : m_FailedTests)
  167. {
  168. Debug.TFLog(string.Format(" |- %1", fail), caller, function);
  169. }
  170. }
  171. }
  172. }
  173. //! Test Framework
  174. class TestFramework : ScriptedEntity
  175. {
  176. private ref TFModule m_OnInitModule;
  177. private ref TFModule m_OnFrameModule;
  178. void TestFramework()
  179. {
  180. SetEventMask(EntityEvent.INIT);
  181. SetEventMask(EntityEvent.FRAME);
  182. m_OnInitModule = new TFModule();
  183. m_OnFrameModule = new TFModule();
  184. }
  185. void ~TestFramework()
  186. {
  187. m_OnInitModule.PrintResult("IM: ", this, "~TestFrameWork");
  188. m_OnFrameModule.PrintResult("FM: ", this, "~TestFrameWork");
  189. }
  190. //---------------------------------------------------------------------------
  191. // Perform tests
  192. //---------------------------------------------------------------------------
  193. protected override void EOnInit(IEntity other, int extra)
  194. {
  195. m_OnInitModule.Run(true, 0);
  196. }
  197. protected override void EOnFrame(IEntity other, float timeSlice)
  198. {
  199. if (m_OnFrameModule.Run(false, timeSlice))
  200. GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).Call(Delete);
  201. }
  202. //---------------------------------------------------------------------------
  203. // Add a test
  204. //---------------------------------------------------------------------------
  205. protected void AddInitTest(string test)
  206. {
  207. m_OnInitModule.AddTest(this, test, false);
  208. }
  209. protected void AddFrameTest(string test)
  210. {
  211. m_OnFrameModule.AddTest(this, test, true);
  212. }
  213. //---------------------------------------------------------------------------
  214. // Asserts
  215. //---------------------------------------------------------------------------
  216. protected bool Assert(bool condition)
  217. {
  218. if (!condition)
  219. ErrorEx("ASSERTION FAILED.");
  220. return condition;
  221. }
  222. //---------------------------------------------------------------------------
  223. // Helpers
  224. //---------------------------------------------------------------------------
  225. TFResult NTFR(TFR result)
  226. {
  227. return new TFResult(result);
  228. }
  229. TFResult BTFR(bool result)
  230. {
  231. if (result)
  232. return new TFResult(TFR.SUCCESS);
  233. else
  234. return new TFResult(TFR.FAIL);
  235. }
  236. TFResult CTFR()
  237. {
  238. return new TFResult(TFR.SUCCESS);
  239. }
  240. }