y_testing.inc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. #if defined _INC_y_testing
  2. #endinput
  3. #endif
  4. #define _INC_y_testing
  5. /**
  6. * <library name="y_testing">
  7. * <section>
  8. * Description
  9. * </section>
  10. * Runs any functions named as tests when the Testing_Run function is called.
  11. * <section>
  12. * Version
  13. * </section>
  14. * 1.0
  15. * </library>
  16. *//** *//*
  17. Legal:
  18. Version: MPL 1.1
  19. The contents of this file are subject to the Mozilla Public License Version
  20. 1.1 the "License"; you may not use this file except in compliance with
  21. the License. You may obtain a copy of the License at
  22. http://www.mozilla.org/MPL/
  23. Software distributed under the License is distributed on an "AS IS" basis,
  24. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  25. for the specific language governing rights and limitations under the
  26. License.
  27. The Original Code is the YSI framework.
  28. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  29. Portions created by the Initial Developer are Copyright C 2011
  30. the Initial Developer. All Rights Reserved.
  31. Contributors:
  32. Y_Less
  33. koolk
  34. JoeBullet/Google63
  35. g_aSlice/Slice
  36. Misiur
  37. samphunter
  38. tianmeta
  39. maddinat0r
  40. spacemud
  41. Crayder
  42. Dayvison
  43. Ahmad45123
  44. Zeex
  45. irinel1996
  46. Yiin-
  47. Chaprnks
  48. Konstantinos
  49. Masterchen09
  50. Southclaws
  51. PatchwerkQWER
  52. m0k1
  53. paulommu
  54. udan111
  55. Thanks:
  56. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  57. ZeeX - Very productive conversations.
  58. koolk - IsPlayerinAreaEx code.
  59. TheAlpha - Danish translation.
  60. breadfish - German translation.
  61. Fireburn - Dutch translation.
  62. yom - French translation.
  63. 50p - Polish translation.
  64. Zamaroht - Spanish translation.
  65. Los - Portuguese translation.
  66. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes for
  67. me to strive to better.
  68. Pixels^ - Running XScripters where the idea was born.
  69. Matite - Pestering me to release it and using it.
  70. Very special thanks to:
  71. Thiadmer - PAWN, whose limits continue to amaze me!
  72. Kye/Kalcor - SA:MP.
  73. SA:MP Team past, present and future - SA:MP.
  74. Optional plugins:
  75. Gamer_Z - GPS.
  76. Incognito - Streamer.
  77. Me - sscanf2, fixes2, Whirlpool.
  78. */
  79. forward bool:_Testing_End();
  80. #include <a_samp>
  81. #include "y_debug"
  82. #include "..\YSI_Storage\y_amx"
  83. #include "..\YSI_Internal\y_thirdpartyinclude"
  84. #include "..\YSI_Internal\y_shortvar"
  85. #if defined YSI_TESTS
  86. #if defined INCLUDE_TESTS
  87. #error Incompatible testing options (YSI_TESTS + INCLUDE_TESTS)
  88. #endif
  89. #if !defined RUN_TESTS
  90. #define RUN_TESTS
  91. #endif
  92. #endif
  93. #if defined INCLUDE_TESTS
  94. #define RUN_TESTS
  95. #define Debug_PrintT va_printf
  96. #elseif defined RUN_TESTS
  97. #define _AUTO_RUN_TESTS
  98. #define Debug_PrintT va_printf
  99. #else
  100. #if _DEBUG > 0 || defined _YSI_SPECIAL_DEBUG
  101. #define RUN_TESTS
  102. #define _AUTO_RUN_TESTS
  103. #define Debug_PrintT va_printf
  104. #else
  105. #define Debug_PrintT(%0);
  106. #endif
  107. #endif
  108. #if defined LIGHT_TEST_REPORT
  109. #define TEST_REPORT(%0) H@(%0)
  110. #else
  111. #define TEST_REPORT(%0) printf(%0)
  112. #endif
  113. #define Y_TESTING_DIALOG_ID (0x7974) // "yt"
  114. #define TEST_TRUE(%0) Testing_Test(!!%0)
  115. #define TEST_FALSE(%0) Testing_Test(!%0)
  116. #define TEST_NULL(%0) Testing_Test(0 == %0)
  117. #define TEST_NOT_NULL(%0) Testing_Test(0 != %0)
  118. #define TEST_N(%0,%1) Testing_Test(%1 == %0)
  119. #define TEST_TRUE_EX(%0,%2) Testing_Test(bool:(%0), (%2))
  120. #define TEST_FALSE_EX(%0,%2) Testing_Test(!(%0), (%2))
  121. #define TEST_NULL_EX(%0,%2) Testing_Test((%0) == 0, (%2))
  122. #define TEST_N_EX(%0,%1,%2) Testing_Test((%0) == (%1), (%2))
  123. #define TEST_MSG "\2\2\2\2\2"
  124. #define TEST_FAILED "FAIL:"
  125. #define TEST_PASSED "PASS!"
  126. #define _Y_TESTEQ(%0) "\"%0\"")
  127. #define _Y_TESTDQ:_Y_TESTEQ(%0"%1"%2) _Y_TESTDQ:_Y_TESTEQ(%0\x22;%1\x22;%2)
  128. #define _Y_TESTCB:_Y_TESTDQ:_Y_TESTEQ(%0)%1) _Y_TESTCB:_Y_TESTDQ:_Y_TESTEQ(%0\x29;%1)
  129. #define _Y_TESTOB:_Y_TESTCB:_Y_TESTDQ:_Y_TESTEQ(%0(%1) _Y_TESTOB:_Y_TESTCB:_Y_TESTDQ:_Y_TESTEQ(%0\x28;%1)
  130. #define ASSERT(%0) Testing_Test(%0,TEST_MSG" %s", _Y_TESTOB:_Y_TESTCB:_Y_TESTDQ:_Y_TESTEQ(%0)
  131. #define ASSERT_TRUE(%0) ASSERT(!!%0)
  132. #define ASSERT_FALSE(%0) ASSERT(!%0)
  133. #define ASSERT_NULL(%0) ASSERT(0 == %0)
  134. #define ASSERT_N:%1(%0) ASSERT(%1 == %0)
  135. #define ASK(%0) Testing_Ask(playerid,%0)
  136. static stock const
  137. Y_TESTING_TEST = _A<yQ@_>,
  138. Y_TESTING_INIT = _A<_yQ@>,
  139. Y_TESTING_SHUT = _A<yQ_@>,
  140. Y_TESTING_PTEST = _A<_@yQ>,
  141. Y_TESTING_PINIT = _A<_y@Q>,
  142. Y_TESTING_PSHUT = _A<y_@Q>,
  143. Y_TESTING_BEFORE = _A<yB_@>,
  144. Y_TESTING_AFTER = _A<yA_@>
  145. ;
  146. static stock
  147. YSI_g_sCurTest = 0,
  148. YSI_g_sCurHeap = 0,
  149. YSI_g_sFailTests = 0,
  150. YSI_g_sInTest = false,
  151. YSI_g_sTestResult,
  152. YSI_g_sFailMessage[512],
  153. YSI_g_sPlayer = cellmax,
  154. bool:YSI_gTestComplete,
  155. bool:YSI_g_sAsked,
  156. YSI_g_sTests,
  157. YSI_g_sFails;
  158. stock
  159. YSI_gCurTestName[32];
  160. #if defined RUN_TESTS
  161. #define Test:%1() forward bool:yQ@_%1(); public bool:yQ@_%1() for(new bool:__once = (_Testing_Start("\0\0"#%1), TEST_REPORT("*** Test %s start", YSI_gCurTestName) || true); __once; __once = _Testing_End())
  162. #define TestInit:%1() forward _yQ@%1(); public _yQ@%1() for (new bool:__once = true; __once; __once = false)
  163. #define TestClose:%1() forward yQ_@%1(); public yQ_@%1() for (new bool:__once = true; __once; __once = false)
  164. #define TestBeforeEach:%1() forward yB_@%1(); public yB_@%1()
  165. #define TestAfterEach:%1() forward yA_@%1(); public yA_@%1()
  166. #define PTest:%1(%2) forward bool:_@yQ%1(%2); public bool:_@yQ%1(%2) for(new bool:__once = (_Testing_Start("\0\0"#%1), TEST_REPORT("*** Player Test %s start", YSI_gCurTestName) || true); __once; __once = _Testing_End())
  167. #define PTestInit:%1(%2) forward _y@Q%1(%2); public _y@Q%1(%2) for (new bool:__once = true; __once; __once = false)
  168. #define PTestClose:%1(%2) forward y_@Q%1(%2); public y_@Q%1(%2) for (new bool:__once = true; __once; __once = false)
  169. #else
  170. #define Test:%1() stock bool:yQ@_%1()
  171. #define TestInit:%1() stock _yQ@%1()
  172. #define TestClose:%1() stock yQ_@%1()
  173. #define TestBeforeEach:%1() stock yB_@%1()
  174. #define TestAfterEach:%1() stock yA_@%1()
  175. #define PTest:%1(%2) stock bool:_@yQ%1(%2)
  176. #define PTestInit:%1(%2) stock _y@Q%1(%2)
  177. #define PTestClose:%1(%2) stock y_@Q%1(%2)
  178. #endif
  179. // These all need to come AFTER the types are defined in case the have tests.
  180. #include "..\YSI_Internal\y_version"
  181. #include "..\YSI_Storage\y_amx"
  182. #include "..\YSI_Internal\y_shortfunc"
  183. #include "y_debug"
  184. #include "..\YSI_Internal\y_natives"
  185. #include "..\YSI_Coding\y_va"
  186. /*-------------------------------------------------------------------------*//**
  187. * <param name="name">Name of the current function.</param>
  188. * <remarks>
  189. * Gets a reference to the
  190. * </remarks>
  191. *//*------------------------------------------------------------------------**/
  192. stock _Testing_Start(name[])
  193. {
  194. YSI_gTestComplete = false;
  195. // Gets a reference to the name string, which is also an intrusive linked
  196. // list of failures.
  197. name[0] = name[1] = 0,
  198. YSI_g_sCurTest = ref(name);
  199. // My very first legitimate usage of `heapspace()` for something other than
  200. // as a dummy no-op function call! I'm actually quite happy I found a use
  201. // for it!
  202. YSI_g_sCurHeap = heapspace();
  203. P:3("_Testing_Start %d %d %s = %d", name[0], name[1], name[2], YSI_g_sCurTest);
  204. YSI_gCurTestName[0] = '\0',
  205. strcpy(YSI_gCurTestName, name[2]);
  206. }
  207. /*-------------------------------------------------------------------------*//**
  208. * <param name="playerid">Player to ask a question to.</param>
  209. * <param name="str">What to ask.</param>
  210. * <param name="va_args">Additional data.</param>
  211. * <remarks>
  212. * Calls a dialog to ask the player if the given test actually passed.
  213. * </remarks>
  214. *//*------------------------------------------------------------------------**/
  215. stock Testing_Ask(playerid, str[] = "", va_args<>)
  216. {
  217. va_format(YSI_g_sFailMessage, sizeof (YSI_g_sFailMessage), str, va_start<2>);
  218. ShowPlayerDialog(playerid, Y_TESTING_DIALOG_ID, DIALOG_STYLE_MSGBOX, "Did the test pass?", YSI_g_sFailMessage, "Yes", "No");
  219. YSI_g_sAsked = true;
  220. }
  221. stock Testing_Test(bool:x, str[] = "", va_args<>)
  222. {
  223. P:3("Testing_Test called: %i, \"%s\"", x, str);
  224. ++YSI_g_sTests;
  225. if (!x)
  226. {
  227. ++YSI_g_sFails;
  228. if (numargs() == 2)
  229. {
  230. P:T(TEST_FAILED " %s", str);
  231. }
  232. else
  233. {
  234. if (str[0] == '\2')
  235. {
  236. strunpack(str, !TEST_FAILED, 6);
  237. str[5] = ' ';
  238. }
  239. P:T(str, va_start<2>);
  240. }
  241. }
  242. #if defined TEST_SHOW_PASSES
  243. else
  244. {
  245. P:T(TEST_PASSED, va_start<2>);
  246. }
  247. #endif
  248. }
  249. /*-------------------------------------------------------------------------*//**
  250. * <param name="name">Name of the current function.</param>
  251. * <remarks>
  252. * Gets a reference to the
  253. * </remarks>
  254. *//*------------------------------------------------------------------------**/
  255. stock bool:_Testing_End()
  256. {
  257. YSI_gTestComplete = true;
  258. new
  259. space = heapspace();
  260. Testing_Test(YSI_g_sCurHeap == space, TEST_FAILED " Heap allocation leak - was: %d, now: %d", YSI_g_sCurHeap, space);
  261. TEST_REPORT(" ");
  262. return false;
  263. }
  264. /*-------------------------------------------------------------------------*//**
  265. * <param name="tests">Number of tests run.</param>
  266. * <param name="fails">Number of tests which failed.</param>
  267. * <param name="buffer">The name of the first test which failed.</param>
  268. * <returns>
  269. * Wether all tests were sucessful or not.
  270. * </returns>
  271. * <remarks>
  272. * -
  273. *
  274. * native Testing_Run(&amp;tests, &amp;fails, buffer[33] = "");
  275. *
  276. * </remarks>
  277. *//*------------------------------------------------------------------------**/
  278. stock bool:Testing_Run(&tests, &fails, lastfail[33] = "", bool:p = false)
  279. {
  280. P:3("bool:Testing_Run called: %i, %i, \"%s\", %i", tests, fails, lastfail, p);
  281. #pragma unused p, lastfail
  282. #if defined RUN_TESTS
  283. P:2("Testing_Run() called");
  284. new
  285. idx,
  286. bidx,
  287. buffer2[32],
  288. buffer[32];
  289. YSI_g_sCurTest = YSI_g_sFailTests = 0;
  290. while ((idx = AMX_GetPublicNamePrefix(idx, buffer, Y_TESTING_TEST)))
  291. {
  292. strunpack(buffer, buffer);
  293. while ((bidx = AMX_GetPublicNamePrefix(bidx, buffer2, Y_TESTING_BEFORE))) {
  294. strunpack(buffer2, buffer2);
  295. new
  296. i = 4,
  297. bool:match = true
  298. ;
  299. while (buffer[i] != EOS && buffer2[i] != EOS) {
  300. if (buffer[i] != buffer2[i]) {
  301. match = false;
  302. break;
  303. }
  304. i++;
  305. }
  306. if (match) {
  307. CallLocalFunction(buffer2, "");
  308. }
  309. }
  310. // Call the setup function if there is one.
  311. buffer[0] = '_',
  312. buffer[1] = 'y',
  313. buffer[2] = 'Q',
  314. buffer[3] = '@',
  315. CallLocalFunction(buffer, "");
  316. // Call the test.
  317. buffer[0] = 'y',
  318. buffer[1] = 'Q',
  319. buffer[2] = '@',
  320. buffer[3] = '_',
  321. fails = YSI_g_sFails;
  322. P:5("Testing_Run(): Calling %s", unpack(buffer[1]));
  323. YSI_g_sInTest = true;
  324. CallLocalFunction(buffer, "");
  325. YSI_g_sInTest = false;
  326. Testing_Test(YSI_gTestComplete, "Test did not complete (possible crash).\n");
  327. if (YSI_g_sFails != fails)
  328. {
  329. WriteAmxMemory(YSI_g_sCurTest, YSI_g_sFailTests),
  330. WriteAmxMemory(YSI_g_sCurTest + 4, YSI_g_sFails - fails),
  331. YSI_g_sFailTests = YSI_g_sCurTest;
  332. }
  333. #if !defined TEST_SHOW_PASSES
  334. else
  335. {
  336. TEST_REPORT(TEST_PASSED);
  337. TEST_REPORT(" ");
  338. }
  339. #endif
  340. buffer[2] = '_',
  341. buffer[3] = '@',
  342. CallLocalFunction(buffer, "");
  343. while ((bidx = AMX_GetPublicNamePrefix(bidx, buffer2, Y_TESTING_AFTER))) {
  344. strunpack(buffer2, buffer2);
  345. new
  346. i = 4,
  347. bool:match = true
  348. ;
  349. while (buffer[i] != EOS && buffer2[i] != EOS) {
  350. if (buffer[i] != buffer2[i]) {
  351. match = false;
  352. break;
  353. }
  354. i++;
  355. }
  356. if (match) {
  357. CallLocalFunction(buffer2, "");
  358. }
  359. }
  360. }
  361. tests = YSI_g_sTests;
  362. fails = YSI_g_sFails;
  363. return fails == 0;
  364. #else
  365. #pragma unused tests, fails, lastfail
  366. return true;
  367. #endif
  368. }
  369. /*-------------------------------------------------------------------------*//**
  370. * <param name="playerid">Player to test on.</param>
  371. * <param name="idx">Next test to run.</param>
  372. * <param name="tests">Number of tests run.</param>
  373. * <param name="fails">Number of tests which failed.</param>
  374. * <param name="buffer">The name of the first test which failed.</param>
  375. * <returns>
  376. * Wether all tests were sucessful or not.
  377. * </returns>
  378. * <remarks>
  379. * -
  380. *
  381. * native bool:Testing_Player(playerid, &amp;idx, &amp;tests, &amp;fails, lastfail[33] = "", bool:p = false);
  382. *
  383. * </remarks>
  384. *//*------------------------------------------------------------------------**/
  385. stock bool:Testing_Player(playerid, &idx, &tests, &fails, lastfail[33] = "", bool:p = false)
  386. {
  387. P:3("bool:Testing_Player called: %i, %i, %i, %i, \"%s\", %i", playerid, idx, tests, fails, lastfail, p);
  388. #pragma unused p
  389. #if defined RUN_TESTS
  390. P:2("Testing_Player() called");
  391. new
  392. buffer[32];
  393. if ((idx = AMX_GetPublicNamePrefix(YSI_g_sPlayer, buffer, Y_TESTING_PTEST)))
  394. {
  395. strunpack(buffer, buffer);
  396. // Call the setup function if there is one.
  397. buffer[0] = '_';
  398. buffer[1] = 'y';
  399. buffer[2] = '@';
  400. buffer[3] = 'Q';
  401. CallLocalFunction(buffer, "");
  402. // Call the test.
  403. buffer[1] = '@';
  404. buffer[2] = 'y';
  405. fails = YSI_g_sFails;
  406. P:5("Testing_Player(): Calling %s", buffer[6]);
  407. YSI_g_sInTest = true;
  408. CallLocalFunction(buffer, "");
  409. #if !defined TEST_SHOW_PASSES
  410. if (YSI_g_sFails == fails)
  411. {
  412. TEST_REPORT(TEST_PASSED);
  413. TEST_REPORT(" ");
  414. }
  415. #endif
  416. }
  417. tests = YSI_g_sTests;
  418. fails = YSI_g_sFails;
  419. return fails == 0;
  420. #else
  421. #pragma unused tests, fails, lastfail
  422. return true;
  423. #endif
  424. }
  425. forward OnTestsComplete(tests, fails);
  426. #if defined RUN_TESTS
  427. #if defined _AUTO_RUN_TESTS
  428. #if defined FILTERSCRIPT
  429. // Hook main in gamemodes.
  430. public OnFilterScriptInit()
  431. {
  432. #if defined Testing_OnFilterScriptInit
  433. Testing_OnFilterScriptInit();
  434. #endif
  435. Testing_RunAll();
  436. }
  437. #if defined _ALS_OnFilterScriptInit
  438. #undef OnFilterScriptInit
  439. #else
  440. #define _ALS_OnFilterScriptInit
  441. #endif
  442. #define OnFilterScriptInit Testing_OnFilterScriptInit
  443. #if defined Testing_OnFilterScriptInit
  444. forward Testing_OnFilterScriptInit();
  445. #endif
  446. #else
  447. // Hook main in gamemodes.
  448. main()
  449. {
  450. #if defined Testing_main
  451. Testing_main();
  452. #endif
  453. Testing_RunAll();
  454. }
  455. #if defined _ALS_main
  456. #undef main
  457. #else
  458. #define _ALS_main
  459. #endif
  460. #define main forward Testing_main(); public Testing_main
  461. #endif
  462. #endif
  463. Testing_Next(playerid)
  464. {
  465. YSI_g_sInTest = false;
  466. new
  467. buffer[32];
  468. for ( ; ; )
  469. {
  470. new
  471. fails = YSI_g_sFails;
  472. // Get the last test (nicely fails for cellmax).
  473. if ((YSI_g_sPlayer = AMX_GetPublicNamePrefix(YSI_g_sPlayer, buffer, Y_TESTING_PTEST)))
  474. {
  475. strunpack(buffer, buffer);
  476. // Call the shutdown function if there is one.
  477. buffer[0] = 'y';
  478. buffer[1] = '_';
  479. buffer[2] = '@';
  480. buffer[3] = 'Q';
  481. CallLocalFunction(buffer, "i", playerid);
  482. }
  483. // Get the new test, but don't store the index.
  484. if (AMX_GetPublicNamePrefix(YSI_g_sPlayer, buffer, Y_TESTING_PTEST))
  485. {
  486. YSI_g_sAsked = false;
  487. strunpack(buffer, buffer);
  488. // Call the setup function if there is one.
  489. buffer[0] = '_';
  490. buffer[1] = 'y';
  491. buffer[2] = '@';
  492. buffer[3] = 'Q';
  493. CallLocalFunction(buffer, "i", playerid);
  494. // Call the test.
  495. buffer[1] = '@';
  496. buffer[2] = 'y';
  497. P:5("Testing_Next(): Calling %s", unpack(buffer[1]));
  498. YSI_g_sInTest = true;
  499. CallLocalFunction(buffer, "i", playerid);
  500. }
  501. else
  502. {
  503. YSI_g_sAsked = true;
  504. // No more tests.
  505. printf("*** Tests: %d, Fails: %d", YSI_g_sTests, YSI_g_sFails);
  506. if (!YSI_g_sFails)
  507. {
  508. TEST_REPORT(" ");
  509. TEST_REPORT(" ||==========================|| ");
  510. TEST_REPORT(" || ALL PLAYER TESTS PASSED! || ");
  511. TEST_REPORT(" ||==========================|| ");
  512. TEST_REPORT(" ");
  513. }
  514. }
  515. // If the test needs a player but doesn't ask them anything
  516. // then we can't wait for "OnDialogResponse" to run the next
  517. // one.
  518. if (YSI_g_sAsked)
  519. {
  520. break;
  521. }
  522. else if (fails == YSI_g_sFails)
  523. {
  524. TEST_REPORT(TEST_PASSED);
  525. }
  526. }
  527. }
  528. public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
  529. {
  530. if (dialogid == Y_TESTING_DIALOG_ID)
  531. {
  532. ++YSI_g_sTests;
  533. if (response)
  534. {
  535. // Pass.
  536. TEST_REPORT(TEST_PASSED);
  537. }
  538. else
  539. {
  540. // Fail.
  541. TEST_REPORT(TEST_FAILED " %s", YSI_g_sFailMessage);
  542. ++YSI_g_sFails;
  543. }
  544. Testing_Next(playerid);
  545. return 1;
  546. }
  547. #if defined Testing_OnDialogResponse
  548. return Testing_OnDialogResponse(playerid, dialogid, response, listitem, inputtext);
  549. #else
  550. return 1;
  551. #endif
  552. }
  553. #if defined _ALS_OnDialogResponse
  554. #undef OnDialogResponse
  555. #else
  556. #define _ALS_OnDialogResponse
  557. #endif
  558. #define OnDialogResponse Testing_OnDialogResponse
  559. #if defined Testing_OnDialogResponse
  560. forward Testing_OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]);
  561. #endif
  562. forward OnRuntimeError(code, &bool:suppress);
  563. public OnRuntimeError(code, &bool:suppress)
  564. {
  565. if (YSI_g_sInTest)
  566. {
  567. // Fail the current test if we see any runtime errors. Requires the
  568. // crashdetect plugin to function, but not to compile and run.
  569. Testing_Test(false, "Runtime error detected");
  570. }
  571. #if defined Testing_OnRuntimeError
  572. return Testing_OnRuntimeError(code, suppress);
  573. #else
  574. return 1;
  575. #endif
  576. }
  577. #if defined _ALS_OnRuntimeError
  578. #undef OnRuntimeError
  579. #else
  580. #define _ALS_OnRuntimeError
  581. #endif
  582. #define OnRuntimeError Testing_OnRuntimeError
  583. #if defined Testing_OnRuntimeError
  584. forward Testing_OnRuntimeError(code, &bool:suppress);
  585. #endif
  586. public OnPlayerSpawn(playerid)
  587. {
  588. if (YSI_g_sPlayer == cellmax && !IsPlayerNPC(playerid))
  589. {
  590. TEST_REPORT(" ");
  591. TEST_REPORT(" ||==========================|| ");
  592. TEST_REPORT(" || STARTING PLAYER TESTS... || ");
  593. TEST_REPORT(" ||==========================|| ");
  594. TEST_REPORT(" ");
  595. YSI_g_sTests = 0;
  596. YSI_g_sFails = 0;
  597. Testing_Next(playerid);
  598. }
  599. #if defined Testing_OnPlayerSpawn
  600. return Testing_OnPlayerSpawn(playerid);
  601. #else
  602. return 1;
  603. #endif
  604. }
  605. #if defined _ALS_OnPlayerSpawn
  606. #undef OnPlayerSpawn
  607. #else
  608. #define _ALS_OnPlayerSpawn
  609. #endif
  610. #define OnPlayerSpawn Testing_OnPlayerSpawn
  611. #if defined Testing_OnPlayerSpawn
  612. forward Testing_OnPlayerSpawn(playerid);
  613. #endif
  614. #endif
  615. stock Testing_RunAll()
  616. {
  617. // Disable error messages (as we're likely to generate them).
  618. //state ysi_debug : off;
  619. new
  620. tests,
  621. fails;
  622. TEST_REPORT(" ");
  623. TEST_REPORT(" ||===================|| ");
  624. TEST_REPORT(" || STARTING TESTS... || ");
  625. TEST_REPORT(" ||===================|| ");
  626. TEST_REPORT(" ");
  627. Testing_Run(tests, fails, _, true);
  628. if (YSI_g_sTestResult != 9) printf("*** Test system verification failed!");
  629. else
  630. {
  631. printf("*** Tests: %d, Fails: %d", tests, fails);
  632. if (fails)
  633. {
  634. // List all the failing tests, along with the number of "ASSERT"s
  635. // that didn't pass.
  636. while (YSI_g_sFailTests != 0)
  637. {
  638. printf(" - Test:%s (%d)", deref(YSI_g_sFailTests + 8), ReadAmxMemory(YSI_g_sFailTests + 4)),
  639. YSI_g_sFailTests = ReadAmxMemory(YSI_g_sFailTests);
  640. }
  641. }
  642. else
  643. {
  644. TEST_REPORT(" ");
  645. TEST_REPORT(" ||===================|| ");
  646. TEST_REPORT(" || ALL TESTS PASSED! || ");
  647. TEST_REPORT(" ||===================|| ");
  648. }
  649. TEST_REPORT(" ");
  650. }
  651. //state ysi_debug : on;
  652. CallLocalFunction("OnTestsComplete", "ii", tests, fails);
  653. #if defined TEST_AUTO_EXIT
  654. SendRconCommand("exit");
  655. #endif
  656. //state ysi_debug : on;
  657. }
  658. // Meta tests.
  659. stock Testing_TestRedirect(bool:x, str[] = "", va_args<>)
  660. {
  661. ASSERT(x == bool:YSI_g_sTestResult);
  662. ASSERT(str[0] != '\0');
  663. ASSERT(!strcmp(str, "\2\2\2\2\2", false, 5));
  664. }
  665. Test:y_testing_2()
  666. {
  667. new
  668. t = YSI_g_sTests,
  669. f = YSI_g_sFails;
  670. ASSERT(false == false);
  671. ASSERT(true == true);
  672. ASSERT(TRUE != FALSE);
  673. ASSERT(t + 3 == YSI_g_sTests);
  674. ASSERT(f == YSI_g_sFails);
  675. ASSERT(t + 5 == YSI_g_sTests);
  676. // Fail a fake test on purpose.
  677. //state ysi_debug : on;
  678. P:I("The next test hasn't really failed...");
  679. P:I(" - It is testing the test system.");
  680. //state ysi_debug : off;
  681. ASSERT(false);
  682. ASSERT(f + 1 == YSI_g_sFails); // Not a mistake. Run this test twice to
  683. ASSERT(f + 1 == YSI_g_sFails); // ensure the first one didn't fail too.
  684. --YSI_g_sFails; // Reduce the failure count to not fail the whole suite.
  685. }
  686. TestInit:y_testing_1()
  687. {
  688. YSI_g_sTestResult = 5;
  689. }
  690. Test:y_testing_1()
  691. {
  692. new
  693. x = YSI_g_sTestResult;
  694. ASSERT(FALSE == false);
  695. ASSERT(TRUE == true);
  696. ASSERT(true != false);
  697. ASSERT(isnull(NULL));
  698. ASSERT_TRUE(true);
  699. ASSERT_TRUE(!false);
  700. ASSERT_FALSE(false);
  701. ASSERT_FALSE(!true);
  702. // Test the messages themselves.
  703. #define Testing_Test Testing_TestRedirect
  704. YSI_g_sTestResult = false;
  705. ASSERT(false);
  706. YSI_g_sTestResult = true;
  707. ASSERT(true);
  708. #undef Testing_Test
  709. YSI_g_sTestResult = x + 3;
  710. }
  711. TestClose:y_testing_1()
  712. {
  713. ++YSI_g_sTestResult;
  714. }
  715. #include "..\YSI_Internal\y_shortfunc"