y_testing.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /*----------------------------------------------------------------------------*\
  2. ====================================
  3. y_testing - Run unit tests easilly
  4. ====================================
  5. Description:
  6. Runs any functions named as tests when the Testing_Run function is called.
  7. Legal:
  8. Version: MPL 1.1
  9. The contents of this file are subject to the Mozilla Public License Version
  10. 1.1 (the "License"); you may not use this file except in compliance with
  11. the License. You may obtain a copy of the License at
  12. http://www.mozilla.org/MPL/
  13. Software distributed under the License is distributed on an "AS IS" basis,
  14. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  15. for the specific language governing rights and limitations under the
  16. License.
  17. The Original Code is the YSI testing include.
  18. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  19. Portions created by the Initial Developer are Copyright (C) 2011
  20. the Initial Developer. All Rights Reserved.
  21. Contributors:
  22. ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice
  23. Thanks:
  24. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  25. ZeeX - Very productive conversations.
  26. koolk - IsPlayerinAreaEx code.
  27. TheAlpha - Danish translation.
  28. breadfish - German translation.
  29. Fireburn - Dutch translation.
  30. yom - French translation.
  31. 50p - Polish translation.
  32. Zamaroht - Spanish translation.
  33. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
  34. for me to strive to better.
  35. Pixels^ - Running XScripters where the idea was born.
  36. Matite - Pestering me to release it and using it.
  37. Very special thanks to:
  38. Thiadmer - PAWN, whose limits continue to amaze me!
  39. Kye/Kalcor - SA:MP.
  40. SA:MP Team past, present and future - SA:MP.
  41. Version:
  42. 1.0
  43. Changelog:
  44. 25/10/10:
  45. Integrated in to YSI.
  46. 06/08/10:
  47. First version
  48. \*----------------------------------------------------------------------------*/
  49. /*#if defined _inc_a_samp || defined _samp_included || defined _inc_y_version
  50. #error y_testing must be the VERY FIRST include in your mode if being used.
  51. #endif
  52. // Now we redefined "native" to do something clever!
  53. // "IsPlayerAttachedObjectSlotUsed" is an issue for us...
  54. // "y_renative" allows native functions to be declared without constantly trying
  55. // to redefine it.
  56. #include "internal\y_renative"
  57. #define native%0(%1); _YSI_NO_TAG_NATIVE:_YSI_RE_NATIVE<%0@|||%1|||%0>_YSI_RE_STOCK<%0|||%1|||_:%0@>
  58. //stock%0(%1){printf(_:_YSI_NO_SQUARE:"native "#%0" called");return _:%0@(%1);}
  59. #define _YSI_RE_STOCK<%0|||%1|||%2> stock%0(%1){print(_:_YSI_NO_SQUARE:"native "#%0" called");return %2(%1);}
  60. #define _YSI_NO_SQUARE:%0);%1(%2[%3]%4);} _YSI_NO_SQUARE:%0);%1(%2%4);}
  61. //#define _YSI_NO_TAG_NATIVE:_YSI_RE_NATIVE<%0:%1|||%2|||%3:%4>%5{%6;%7:%8:%9} _YSI_RE_NATIVE<%1|||%2|||%4>%5{%6;return%8:%9}
  62. #define _YSI_NO_TAG_NATIVE:_YSI_RE_NATIVE<%0:%1|||%2|||%3:%4>_YSI_RE_STOCK<%5:%6|||%7|||_:%8:%9> _YSI_RE_NATIVE<%1|||%2|||%4>_YSI_RE_STOCK<%5:%6|||%7|||%8:%9>
  63. #include <a_samp>*/
  64. #include "internal\y_version"
  65. #include "y_amx"
  66. #include "internal\y_shortfunc"
  67. #include "y_debug"
  68. #include "y_va"
  69. #include "internal\y_natives"
  70. #if defined INCLUDE_TESTS
  71. #define RUN_TESTS
  72. #define Debug_PrintT va_printf
  73. #elseif defined RUN_TESTS
  74. #define _AUTO_RUN_TESTS
  75. #define Debug_PrintT va_printf
  76. #else
  77. #if _DEBUG > 0 || defined _YSI_SPECIAL_DEBUG
  78. #define RUN_TESTS
  79. #define _AUTO_RUN_TESTS
  80. //#if defined _YSI_SPECIAL_DEBUG
  81. // #define TP printf
  82. // //#define TC(%0); %0
  83. #define Debug_PrintT va_printf
  84. //#else
  85. // //#define TP P:0
  86. // //#define TC C:0
  87. //#endif
  88. #else
  89. #define Debug_PrintT(%0);
  90. // #define Tests:%1() stock bool:Tests_@%1()
  91. // #define Test:%1() stock bool:Test_@%1()
  92. // #define TestInit:%1() stock Init_@%1()
  93. // #define TestClose:%1() stock Shut_@%1()
  94. #endif
  95. #endif
  96. #define TEST_TRUE(%0) Testing_Test(!!%0)
  97. #define TEST_FALSE(%0) Testing_Test(!%0)
  98. #define TEST_NULL(%0) Testing_Test(0 == %0)
  99. #define TEST_NOT_NULL(%0) Testing_Test(0 != %0)
  100. #define TEST_N(%0,%1) Testing_Test(%1 == %0)
  101. #define TEST_TRUE_EX(%0,%2) Testing_Test(bool:(%0), (%2))
  102. #define TEST_FALSE_EX(%0,%2) Testing_Test(!(%0), (%2))
  103. #define TEST_NULL_EX(%0,%2) Testing_Test((%0) == 0, (%2))
  104. #define TEST_N_EX(%0,%1,%2) Testing_Test((%0) == (%1), (%2))
  105. #define TEST_MSG "\2\2\2\2\2"
  106. #define TEST_FAILED "FAIL:"
  107. #define TEST_PASSED "PASS!"
  108. //#define TEST_FAILED "*** Test Failed:"
  109. //#define TEST_PASSED "*** Test Passed:"
  110. #define _Y_TESTEQ(%0) "\"%0\"")
  111. #define _Y_TESTDQ:_Y_TESTEQ(%0"%1"%2) _Y_TESTDQ:_Y_TESTEQ(%0\x22;%1\x22;%2)
  112. //#define _Y_TESTCB:_Y_TESTDQ:_Y_TESTEQ(%0)%1) _Y_TESTCB:_Y_TESTDQ:_Y_TESTEQ(%0\x29;%1)
  113. #define _Y_TESTCB:_Y_TESTDQ:_Y_TESTEQ(%0)%1) _Y_TESTCB:_Y_TESTDQ:_Y_TESTEQ(%0\x29;%1)
  114. #define _Y_TESTOB:_Y_TESTCB:_Y_TESTDQ:_Y_TESTEQ(%0(%1) _Y_TESTOB:_Y_TESTCB:_Y_TESTDQ:_Y_TESTEQ(%0\x28;%1)
  115. #define ASSERT(%0) Testing_Test(%0,TEST_MSG" %s", _Y_TESTOB:_Y_TESTCB:_Y_TESTDQ:_Y_TESTEQ(%0)
  116. #define ASSERT_TRUE(%0) ASSERT(!!%0) //Testing_Test(!!%0,__name)
  117. #define ASSERT_FALSE(%0) ASSERT(!%0) //Testing_Test(!%0,__name)
  118. #define ASSERT_NULL(%0) ASSERT(0 == %0) //Testing_Test(0==%0,__name)
  119. #define ASSERT_N:%1(%0) ASSERT(%1 == %0) //Testing_Test(%1==%0,__name)
  120. static stock
  121. YSI_g_sTests,
  122. YSI_g_sFails;
  123. stock Testing_Test(bool:x, str[] = "", va_args<>)
  124. {
  125. P:3("Testing_Test called: %i, \"%s\"", x, str);
  126. ++YSI_g_sTests;
  127. if (!x)
  128. {
  129. ++YSI_g_sFails;
  130. if (numargs() == 2)
  131. {
  132. P:T(TEST_FAILED " %s", va_start<1>);
  133. //printf("*** Test failed: %s", str);
  134. }
  135. else
  136. {
  137. if (str[0] == '\2')
  138. {
  139. strunpack(str, !TEST_FAILED, 6);
  140. str[5] = ' ';
  141. }
  142. P:T(str, va_start<2>);
  143. }
  144. }
  145. else /*if (numargs() == 2)
  146. {
  147. P:T(TEST_PASSED " %s", va_start<1>);
  148. }
  149. else
  150. {
  151. P:T(str, va_start<2>);
  152. if (str[0] == '\2')
  153. {
  154. strunpack(str, !TEST_PASSED, 17);
  155. str[16] = ' ';
  156. }
  157. printf(str);
  158. P:T(str, va_start<2>);*/
  159. {
  160. P:T(TEST_PASSED, va_start<2>);
  161. }
  162. }
  163. /*----------------------------------------------------------------------------*\
  164. Function:
  165. Testing_Run
  166. Params:
  167. &tests - Number of tests run.
  168. &fails - Number of tests which failed.
  169. buffer[33] - The name of the first test which failed.
  170. Return:
  171. Wether all tests were sucessful or not.
  172. Notes:
  173. -
  174. native Testing_Run(&tests, &fails, buffer[33] = "");
  175. \*----------------------------------------------------------------------------*/
  176. stock bool:Testing_Run(&tests, &fails, lastfail[33] = "", bool:p = false)
  177. {
  178. P:3("bool:Testing_Run called: %i, %i, \"%s\", %i", tests, fails, lastfail, p);
  179. #pragma unused p
  180. #if defined RUN_TESTS
  181. P:2("Testing_Run() called");
  182. new
  183. idx,
  184. buffer[32];
  185. while ((idx = AMX_GetPublicName(idx, buffer, "Test_@")))
  186. {
  187. strunpack(buffer, buffer);
  188. ++YSI_g_sTests;
  189. // Call the setup function if there is one.
  190. buffer[0] = 'I';
  191. buffer[1] = 'n';
  192. buffer[2] = 'i';
  193. buffer[3] = 't';
  194. CallLocalFunction(buffer, "");
  195. // Call the test.
  196. buffer[0] = 'T';
  197. buffer[1] = 'e';
  198. buffer[2] = 's';
  199. buffer[3] = 't';
  200. P:5("Testing_Run(): Calling %s", buffer[6]);
  201. if (!CallLocalFunction(buffer, ""))
  202. {
  203. if (YSI_g_sFails)
  204. {
  205. ++YSI_g_sFails;
  206. }
  207. else
  208. {
  209. fails = 0;
  210. // Copy the string over.
  211. while ((lastfail[fails] = buffer[fails + 6])) ++fails;
  212. YSI_g_sFails = 1;
  213. }
  214. //TC(if (p) printf("*** Test failed: %s", buffer[fails + 6]););
  215. }
  216. // Call the shutdown function if there is one.
  217. buffer[0] = 'S';
  218. buffer[1] = 'h';
  219. buffer[2] = 'u';
  220. buffer[3] = 't';
  221. CallLocalFunction(buffer, "");
  222. }
  223. while ((idx = AMX_GetPublicName(idx, buffer, "Tezt_@")))
  224. {
  225. strunpack(buffer, buffer);
  226. //++YSI_g_sTests;
  227. // Call the setup function if there is one.
  228. buffer[0] = 'I';
  229. buffer[1] = 'n';
  230. buffer[2] = 'i';
  231. buffer[3] = 't';
  232. CallLocalFunction(buffer, "");
  233. // Call the test.
  234. buffer[0] = 'T';
  235. buffer[1] = 'e';
  236. buffer[2] = 'z';
  237. buffer[3] = 't';
  238. fails = YSI_g_sFails;
  239. P:5("Testing_Run(): Calling %s", buffer[6]);
  240. CallLocalFunction(buffer, "");
  241. /*if (YSI_g_sFails != fails)
  242. {
  243. if (YSI_g_sFails)
  244. {
  245. ++YSI_g_sFails;
  246. }
  247. else
  248. {
  249. fails = 0;
  250. // Copy the string over.
  251. while ((lastfail[fails] = buffer[fails + 6])) ++fails;
  252. YSI_g_sFails = 1;
  253. }
  254. //C:1(if (p) printf("*** Test failed: %s", buffer[fails + 6]););
  255. }*/
  256. // Call the shutdown function if there is one.
  257. buffer[0] = 'S';
  258. buffer[1] = 'h';
  259. buffer[2] = 'u';
  260. buffer[3] = 't';
  261. CallLocalFunction(buffer, "");
  262. }
  263. tests = YSI_g_sTests;
  264. fails = YSI_g_sFails;
  265. return fails == 0;
  266. #else
  267. #pragma unused tests, fails, lastfail
  268. return true;
  269. #endif
  270. }
  271. #if defined RUN_TESTS
  272. #define Test:%1() forward bool:Tezt_@%1(); public bool:Tezt_@%1() for(new string:__name[]=#%1,bool:__once=(printf("*** Test %s start", __name) || TRUE);__once;__once=(printf(" ") && FALSE))
  273. #define Tests:%1() forward bool:Test_@%1(); public bool:Test_@%1() for(new string:__name[]=#%1,bool:__once=(printf("*** Test %s start", __name) || TRUE);__once;__once=(printf(" ") && FALSE))
  274. #define TestInit:%1() forward Init_@%1(); public Init_@%1() for(new string:__name[]=#%1,bool:__once=TRUE;__once;__once=(printf(" ", __name) && FALSE))
  275. #define TestClose:%1() forward Shut_@%1(); public Shut_@%1() for(new string:__name[]=#%1,bool:__once=TRUE;__once;__once=(printf(" ", __name) && FALSE))
  276. #if defined _AUTO_RUN_TESTS
  277. #if !defined FILTERSCRIPT
  278. // Hook main in gamemodes.
  279. main()
  280. {
  281. // Disable error messages (as we're likely to generate them).
  282. state ysi_debug : off;
  283. CallLocalFunction("Testing_main", "");
  284. new
  285. tests,
  286. fails;
  287. printf(" ");
  288. printf(" ||===================|| ");
  289. printf(" || STARTING TESTS... || ");
  290. printf(" ||===================|| ");
  291. printf(" ");
  292. Testing_Run(tests, fails, _, true);
  293. printf("*** Tests: %d, Fails: %d", tests, fails);
  294. if (!fails)
  295. {
  296. printf(" ");
  297. printf(" ||===================|| ");
  298. printf(" || ALL TESTS PASSED! || ");
  299. printf(" ||===================|| ");
  300. printf(" ");
  301. }
  302. state ysi_debug : on;
  303. }
  304. #define main forward Testing_main(); public Testing_main
  305. #endif
  306. #else
  307. Testing_RunAll()
  308. {
  309. // Disable error messages (as we're likely to generate them).
  310. state ysi_debug : off;
  311. new
  312. tests,
  313. fails;
  314. printf(" ");
  315. printf(" ||===================|| ");
  316. printf(" || STARTING TESTS... || ");
  317. printf(" ||===================|| ");
  318. printf(" ");
  319. Testing_Run(tests, fails, _, true);
  320. printf("*** Tests: %d, Fails: %d", tests, fails);
  321. if (!fails)
  322. {
  323. printf(" ");
  324. printf(" ||===================|| ");
  325. printf(" || ALL TESTS PASSED! || ");
  326. printf(" ||===================|| ");
  327. printf(" ");
  328. }
  329. state ysi_debug : on;
  330. }
  331. #endif
  332. #else
  333. #define Tests:%1() stock bool:Tests_@%1()
  334. #define Test:%1() stock bool:Test_@%1()
  335. #define TestInit:%1() stock Init_@%1()
  336. #define TestClose:%1() stock Shut_@%1()
  337. #endif