CV_Report.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /*-----------------------------------------------------------------------------
  2. * Name: cv_report.c
  3. * Purpose: Report statistics and layout implementation
  4. *-----------------------------------------------------------------------------
  5. * Copyright (c) 2017 - 2018 Arm Limited. All rights reserved.
  6. *----------------------------------------------------------------------------*/
  7. #include "CV_Report.h"
  8. #include <stdio.h>
  9. #include <string.h>
  10. TEST_REPORT test_report;
  11. static AS_STAT current_assertions; /* Current test case assertions statistics */
  12. #define TAS (&test_report.assertions) /* Total assertions */
  13. #define CAS (&current_assertions) /* Current assertions */
  14. #ifdef DISABLE_SEMIHOSTING
  15. #if defined (__CC_ARM)
  16. #pragma import __use_no_semihosting
  17. #elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
  18. __ASM(".global __use_no_semihosting");
  19. #endif
  20. #define PRINT(x)
  21. #define FLUSH()
  22. void _sys_exit(int return_code) {}
  23. #else
  24. #define PRINT(x) MsgPrint x
  25. #define FLUSH() MsgFlush()
  26. #endif // DISABLE_SEMIHOSTING
  27. static uint8_t Passed[] = "PASSED";
  28. static uint8_t Warning[] = "WARNING";
  29. static uint8_t Failed[] = "FAILED";
  30. static uint8_t NotExe[] = "NOT EXECUTED";
  31. /*-----------------------------------------------------------------------------
  32. * Test report function prototypes
  33. *----------------------------------------------------------------------------*/
  34. static BOOL tr_Init (void);
  35. static BOOL tc_Init (void);
  36. static uint8_t *tr_Eval (void);
  37. static uint8_t *tc_Eval (void);
  38. static BOOL StatCount (TC_RES res);
  39. /*-----------------------------------------------------------------------------
  40. * Printer function prototypes
  41. *----------------------------------------------------------------------------*/
  42. static void MsgPrint (const char *msg, ...);
  43. static void MsgFlush (void);
  44. /*-----------------------------------------------------------------------------
  45. * Assert interface function prototypes
  46. *----------------------------------------------------------------------------*/
  47. static BOOL As_File_Result (TC_RES res);
  48. static BOOL As_File_Dbgi (TC_RES res, const char *fn, uint32_t ln, char *desc);
  49. TC_ITF tcitf = {
  50. As_File_Result,
  51. As_File_Dbgi,
  52. };
  53. /*-----------------------------------------------------------------------------
  54. * Test report interface function prototypes
  55. *----------------------------------------------------------------------------*/
  56. BOOL tr_File_Init (void);
  57. BOOL tr_File_Open (const char *title, const char *date, const char *time, const char *fn);
  58. BOOL tr_File_Close (void);
  59. BOOL tc_File_Open (uint32_t num, const char *fn);
  60. BOOL tc_File_Close (void);
  61. REPORT_ITF ritf = {
  62. tr_File_Init,
  63. tr_File_Open,
  64. tr_File_Close,
  65. tc_File_Open,
  66. tc_File_Close
  67. };
  68. /*-----------------------------------------------------------------------------
  69. * Init test report
  70. *----------------------------------------------------------------------------*/
  71. BOOL tr_File_Init (void) {
  72. return (tr_Init());
  73. }
  74. /*-----------------------------------------------------------------------------
  75. * Open test report
  76. *----------------------------------------------------------------------------*/
  77. #if (PRINT_XML_REPORT==1)
  78. BOOL tr_File_Open (const char *title, const char *date, const char *time, const char *fn) {
  79. PRINT(("<?xml version=\"1.0\"?>\n"));
  80. PRINT(("<?xml-stylesheet href=\"TR_Style.xsl\" type=\"text/xsl\" ?>\n"));
  81. PRINT(("<report>\n"));
  82. PRINT(("<test>\n"));
  83. PRINT(("<title>%s</title>\n", title));
  84. PRINT(("<date>%s</date>\n", date));
  85. PRINT(("<time>%s</time>\n", time));
  86. PRINT(("<file>%s</file>\n", fn));
  87. PRINT(("<test_cases>\n"));
  88. #else
  89. BOOL tr_File_Open (const char *title, const char *date, const char *time, const char __attribute__((unused)) *fn) {
  90. PRINT(("%s %s %s \n\n", title, date, time));
  91. #endif
  92. return (__TRUE);
  93. }
  94. /*-----------------------------------------------------------------------------
  95. * Open test case
  96. *----------------------------------------------------------------------------*/
  97. BOOL tc_File_Open (uint32_t num, const char *fn) {
  98. (void)tc_Init ();
  99. #if (PRINT_XML_REPORT==1)
  100. PRINT(("<tc>\n"));
  101. PRINT(("<no>%d</no>\n", num));
  102. PRINT(("<func>%s</func>\n", fn));
  103. PRINT(("<req></req>"));
  104. PRINT(("<meth></meth>"));
  105. PRINT(("<dbgi>\n"));
  106. #else
  107. PRINT(("TEST %02d: %-42s ", num, fn));
  108. #endif
  109. return (__TRUE);
  110. }
  111. /*-----------------------------------------------------------------------------
  112. * Close test case
  113. *----------------------------------------------------------------------------*/
  114. BOOL tc_File_Close (void) {
  115. uint8_t *res = tc_Eval();
  116. #if (PRINT_XML_REPORT==1)
  117. PRINT(("</dbgi>\n"));
  118. PRINT(("<res>%s</res>\n", res));
  119. PRINT(("</tc>\n"));
  120. #else
  121. if ((res==Passed)||(res==NotExe)) {
  122. PRINT(("%s\n", res));
  123. } else {
  124. PRINT(("\n"));
  125. }
  126. #endif
  127. FLUSH();
  128. return (__TRUE);
  129. }
  130. /*-----------------------------------------------------------------------------
  131. * Close test report
  132. *----------------------------------------------------------------------------*/
  133. BOOL tr_File_Close (void) {
  134. #if (PRINT_XML_REPORT==1)
  135. PRINT(("</test_cases>\n"));
  136. PRINT(("<summary>\n"));
  137. PRINT(("<tcnt>%d</tcnt>\n", test_report.tests));
  138. PRINT(("<exec>%d</exec>\n", test_report.executed));
  139. PRINT(("<pass>%d</pass>\n", test_report.passed));
  140. PRINT(("<fail>%d</fail>\n", test_report.failed));
  141. PRINT(("<warn>%d</warn>\n", test_report.warnings));
  142. PRINT(("<tres>%s</tres>\n", tr_Eval()));
  143. PRINT(("</summary>\n"));
  144. PRINT(("</test>\n"));
  145. PRINT(("</report>\n"));
  146. #else
  147. PRINT(("\nTest Summary: %d Tests, %d Executed, %d Passed, %d Failed, %d Warnings.\n",
  148. test_report.tests,
  149. test_report.executed,
  150. test_report.passed,
  151. test_report.failed,
  152. test_report.warnings));
  153. PRINT(("Test Result: %s\n", tr_Eval()));
  154. #endif
  155. FLUSH();
  156. return (__TRUE);
  157. }
  158. /*-----------------------------------------------------------------------------
  159. * Assertion result counter
  160. *----------------------------------------------------------------------------*/
  161. static BOOL As_File_Result (TC_RES res) {
  162. return (StatCount (res));
  163. }
  164. /*-----------------------------------------------------------------------------
  165. * Set debug information state
  166. *----------------------------------------------------------------------------*/
  167. #if (PRINT_XML_REPORT==1)
  168. static BOOL As_File_Dbgi (TC_RES __attribute__((unused)) res, const char *fn, uint32_t ln, char *desc) {
  169. PRINT(("<detail>\n"));
  170. if (desc!=NULL) PRINT(("<desc>%s</desc>\n", desc));
  171. PRINT(("<module>%s</module>\n", fn));
  172. PRINT(("<line>%d</line>\n", ln));
  173. PRINT(("</detail>\n"));
  174. #else
  175. static BOOL As_File_Dbgi (TC_RES res, const char *fn, uint32_t ln, char *desc) {
  176. PRINT(("\n %s (%d)", fn, ln));
  177. if (res==WARNING){ PRINT((" [WARNING]")); }
  178. if (res==FAILED) { PRINT((" [FAILED]")); }
  179. if (desc!=NULL) { PRINT((" %s", desc)); }
  180. #endif
  181. return (__TRUE);
  182. }
  183. /*-----------------------------------------------------------------------------
  184. * Init test report
  185. *----------------------------------------------------------------------------*/
  186. static BOOL tr_Init (void) {
  187. TAS->passed = 0;
  188. TAS->failed = 0;
  189. TAS->warnings = 0;
  190. return (__TRUE);
  191. }
  192. /*-----------------------------------------------------------------------------
  193. * Init test case
  194. *----------------------------------------------------------------------------*/
  195. static BOOL tc_Init (void) {
  196. CAS->passed = 0;
  197. CAS->failed = 0;
  198. CAS->warnings = 0;
  199. return (__TRUE);
  200. }
  201. /*-----------------------------------------------------------------------------
  202. * Evaluate test report results
  203. *----------------------------------------------------------------------------*/
  204. static uint8_t *tr_Eval (void) {
  205. if (test_report.failed > 0U) {
  206. /* Test fails if any test case failed */
  207. return (Failed);
  208. }
  209. else if (test_report.warnings > 0U) {
  210. /* Test warns if any test case warnings */
  211. return (Warning);
  212. }
  213. else if (test_report.passed > 0U) {
  214. /* Test passes if at least one test case passed */
  215. return (Passed);
  216. }
  217. else {
  218. /* No test cases were executed */
  219. return (NotExe);
  220. }
  221. }
  222. /*-----------------------------------------------------------------------------
  223. * Evaluate test case results
  224. *----------------------------------------------------------------------------*/
  225. static uint8_t *tc_Eval (void) {
  226. test_report.tests++;
  227. test_report.executed++;
  228. if (CAS->failed > 0U) {
  229. /* Test case fails if any failed assertion recorded */
  230. test_report.failed++;
  231. return Failed;
  232. }
  233. else if (CAS->warnings > 0U) {
  234. /* Test case warns if any warnings assertion recorded */
  235. test_report.warnings++;
  236. return Warning;
  237. }
  238. else if (CAS->passed > 0U) {
  239. /* Test case passes if at least one assertion passed */
  240. test_report.passed++;
  241. return Passed;
  242. }
  243. else {
  244. /* Assert was not invoked - nothing to evaluate */
  245. test_report.executed--;
  246. return NotExe;
  247. }
  248. }
  249. /*-----------------------------------------------------------------------------
  250. * Statistics result counter
  251. *----------------------------------------------------------------------------*/
  252. static BOOL StatCount (TC_RES res) {
  253. switch (res) {
  254. case PASSED:
  255. CAS->passed++;
  256. TAS->passed++;
  257. break;
  258. case WARNING:
  259. CAS->warnings++;
  260. TAS->warnings++;
  261. break;
  262. case FAILED:
  263. CAS->failed++;
  264. TAS->failed++;
  265. break;
  266. case NOT_EXECUTED:
  267. return (__FALSE);
  268. default:
  269. break;
  270. }
  271. return (__TRUE);
  272. }
  273. /*-----------------------------------------------------------------------------
  274. * Set result
  275. *----------------------------------------------------------------------------*/
  276. TC_RES __set_result (const char *fn, uint32_t ln, TC_RES res, char* desc) {
  277. // save assertion result
  278. switch (res) {
  279. case PASSED:
  280. if (TAS->passed < BUFFER_ASSERTIONS) {
  281. test_report.assertions.info.passed[TAS->passed].module = fn;
  282. test_report.assertions.info.passed[TAS->passed].line = ln;
  283. }
  284. break;
  285. case FAILED:
  286. if (TAS->failed < BUFFER_ASSERTIONS) {
  287. test_report.assertions.info.failed[TAS->failed].module = fn;
  288. test_report.assertions.info.failed[TAS->failed].line = ln;
  289. }
  290. break;
  291. case WARNING:
  292. if (TAS->warnings < BUFFER_ASSERTIONS) {
  293. test_report.assertions.info.warnings[TAS->warnings].module = fn;
  294. test_report.assertions.info.warnings[TAS->warnings].line = ln;
  295. }
  296. break;
  297. case NOT_EXECUTED:
  298. break;
  299. default:
  300. break;
  301. }
  302. // set debug info (if the test case didn't pass)
  303. if (res != PASSED) { (void)tcitf.Dbgi (res, fn, ln, desc); }
  304. // set result
  305. (void)tcitf.Result (res);
  306. return (res);
  307. }
  308. /*-----------------------------------------------------------------------------
  309. * Assert true
  310. *----------------------------------------------------------------------------*/
  311. TC_RES __assert_true (const char *fn, uint32_t ln, uint32_t cond) {
  312. TC_RES res = FAILED;
  313. if (cond != 0U) { res = PASSED; }
  314. (void)__set_result(fn, ln, res, NULL);
  315. return (res);
  316. }
  317. #ifndef DISABLE_SEMIHOSTING
  318. /*-----------------------------------------------------------------------------
  319. * MsgFlush: Flush the standard output
  320. *----------------------------------------------------------------------------*/
  321. static void MsgFlush(void) {
  322. (void)fflush(stdout);
  323. }
  324. #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
  325. #pragma clang diagnostic push
  326. #pragma clang diagnostic ignored "-Wformat-nonliteral"
  327. #endif
  328. /*-----------------------------------------------------------------------------
  329. * MsgPrint: Print a message to the standard output
  330. *----------------------------------------------------------------------------*/
  331. static void MsgPrint (const char *msg, ...) {
  332. va_list args;
  333. va_start(args, msg);
  334. vprintf(msg, args);
  335. va_end(args);
  336. }
  337. #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
  338. #pragma clang diagnostic pop
  339. #endif
  340. #endif // DISABLE_SEMIHOSTING
  341. /*-----------------------------------------------------------------------------
  342. * End of file
  343. *----------------------------------------------------------------------------*/