1 /*
2 * BCUnit - A Unit testing framework library for C.
3 * Copyright (C) 2001 Anil Kumar
4 * Copyright (C) 2004-2006 Anil Kumar, Jerry St.Clair
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 /*
22 * Implementation of the Curses based Test Interface.
23 *
24 * 01/Nov/2001 Started Curses based interface for BCUnit. (AK)
25 *
26 * 04/Nov/2001 Added Scrolling Capability to the Details Window. (AK)
27 *
28 * 24/Nov/2001 Added List and Show Failure Capability to the Details Window.
29 * Also added group initialization failure message handler. (AK)
30 *
31 * 09-Aug-2004 New interface, made all curses local functions static. (JDS)
32 *
33 * 30-Apr-2006 Suite/test selection is now by number rather than name.
34 * Inactive suites/tests now reported.
35 * Interface supports (de)activation of tests/suites.
36 * Help function added for both menu levels.
37 * Option menu added. (JDS)
38 *
39 * 02-May-2006 Added internationalization hooks. (JDS)
40 */
41
42 /** @file
43 * Curses test interface with interactive output (implementation).
44 */
45 /** @addtogroup Curses
46 @{
47 */
48
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <ctype.h>
52 #include <assert.h>
53 #include <string.h>
54 #include <curses.h>
55
56 #include "BCUnit.h"
57 #include "TestDB.h"
58 #include "Util.h"
59 #include "TestRun.h"
60 #include "CUCurses.h"
61 #include "BCUnit_intl.h"
62
63 /*=================================================================
64 * Global / Static data definitions
65 *=================================================================*/
66
67 /* Type Definitions */
68
69 #ifndef false
70 #define false (0) /**< Local boolean definition for false. */
71 #endif
72
73 #ifndef true
74 #define true (~false) /**< Local boolean definition for true. */
75 #endif
76
77 /** Curses interface status flag. */
78 typedef enum
79 {
80 CONTINUE = 1, /**< Continue processing commands in current menu. */
81 MOVE_UP, /**< Move up to the previous menu. */
82 STOP /**< Stop processing (user selected 'Quit'). */
83 } STATUS;
84
85 /** Menu type. */
86 typedef enum
87 {
88 MAIN_MENU = 1,
89 GROUP_MENU
90 } MENU_TYPE;
91
92 /** Pointers to curses interface windows. */
93 typedef struct
94 {
95 WINDOW* pMainWin; /**< Main window. */
96 WINDOW* pTitleWin; /**< Title window. */
97 WINDOW* pProgressWin; /**< Progress bar window. */
98 WINDOW* pSummaryWin; /**< Summary window. */
99 WINDOW* pRunSummaryWin; /**< Run Summary window. */
100 WINDOW* pDetailsWin; /**< Details window. */
101 WINDOW* pOptionsWin; /**< Options window. */
102 } APPWINDOWS;
103
104 /** Window elements. */
105 typedef struct
106 {
107 WINDOW* pPad; /**< Pointer to the pad. */
108 unsigned int uiRows; /**< Number of rows in pad. */
109 unsigned int uiColumns; /**< Number of columns in pad. */
110 unsigned int uiPadRow; /**< Current pad row. */
111 unsigned int uiPadCol; /**< Current pad column. */
112 unsigned int uiWinLeft; /**< Left position of containing window. */
113 unsigned int uiWinTop; /**< Top position of containing window. */
114 unsigned int uiWinRows; /**< Number of rows in containing window. */
115 unsigned int uiWinColumns; /**< Number of columns in containing window. */
116 } APPPAD;
117
118 /*
119 * Constants definitions
120 */
121 /** Standard string length. */
122 #define STRING_LENGTH 128
123 /** String holding main menu run options. */
124 static const char* MAIN_OPTIONS =
125 N_("(R)un (S)elect (L)ist (A)ctivate (F)ailures (O)ptions (H)elp (Q)uit");
126 /** String holding suite menu run options. */
127 static const char* SUITE_OPTIONS =
128 N_("(R)un (S)elect (L)ist (A)ctivate (F)ailures (O)ptions (H)elp (U)p (Q)uit");
129
130 /*
131 * Color Pairs Initialized for the Various Parameter Display
132 */
133 static const int CLEAR_COLOR = 1; /**< Clear color.*/
134 static const int TITLE_COLOR = 2; /**< Title color.*/
135 static const int PROGRESS_BACKGROUND_COLOR = 3; /**< progress bar background color.*/
136 static const int PROGRESS_SUCCESS_COLOR = 4; /**< Progress bar success color.*/
137 static const int PROGRESS_FAILURE_COLOR = 5; /**< Progress bar failure color.*/
138 static const int MENU_COLOR = 6; /**< Menu color.*/
139
140 static const char* const f_szProgress = N_("Progress "); /**< Text for progress bar. */
141
142 static const char* f_szOptions = NULL; /**< String containing options. */
143
144 static CU_pTest f_pCurrentTest = NULL; /**< Pointer to the test currently being run. */
145 static CU_pSuite f_pCurrentSuite = NULL; /**< Pointer to the suite currently being run. */
146
147 static unsigned int f_uiTotalTests = 0; /**< Number of tests in registered suites. */
148 static unsigned int f_uiTestsRun = 0; /**< Number of tests actually run. */
149 static unsigned int f_uiTestsSkipped = 0; /**< Number of tests skipped during run. */
150 static unsigned int f_uiTestsFailed = 0; /**< Number of tests having failed assertions. */
151 static unsigned int f_uiTestsRunSuccessful = 0; /**< Number of tests run with no failed assertions. */
152
153 static unsigned int f_uiTotalSuites = 0; /**< Number of registered suites. */
154 static unsigned int f_uiSuitesSkipped = 0; /**< Number of suites skipped during run. */
155
156 static short f_nLeft; /**< Left window position. */
157 static short f_nTop; /**< Top window position. */
158 static short f_nWidth; /**< Width of window. */
159 static short f_nHeight; /**< Height of window. */
160
161 /** Common width measurements for output formatting. */
162 static size_t f_yes_width = 0;
163 static size_t f_no_width = 0;
164
165 /** Pointers to curses interface windows. */
166 static APPWINDOWS application_windows = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
167 /** Details window definition. */
168 static APPPAD details_pad = {NULL, 0, 0, 0, 0, 0, 0, 0, 0};
169
170 /*=================================================================
171 * Static function forward declarations
172 *=================================================================*/
173 static bool initialize_windows(void);
174 static void uninitialize_windows(void);
175
176 static void refresh_windows(void);
177 static void refresh_title_window(void);
178 static void refresh_progress_window(void);
179 static void refresh_summary_window(void);
180 static void refresh_run_summary_window(void);
181 static void refresh_details_window(void);
182 static void refresh_options_window(void);
183 static void show_detail_window_message(const char* msg);
184
185 static bool create_pad(APPPAD* pPad, WINDOW* pParent, unsigned int uiRows, unsigned int uiCols);
186 static void scroll_window(int nCommand, APPPAD* pPad, void (*parent_refresh)(void));
187
188 static bool test_initialize(void);
189
190 static void show_progress_bar(void);
191 static const char* get_hotkey(const char* szStr, int* pPos);
192 static void read_input_string(const char szPropmt[], char szValue[], int nBytes);
193
194 static STATUS curses_registry_level_run(CU_pTestRegistry pRegistry);
195 static STATUS curses_suite_level_run(CU_pSuite pSuite);
196 static STATUS curses_set_options_run(void);
197
198 static CU_ErrorCode curses_run_all_tests(CU_pTestRegistry pRegistry);
199 static CU_ErrorCode curses_run_suite_tests(CU_pSuite pSuite);
200 static CU_ErrorCode curses_run_single_test(CU_pSuite pSuite, CU_pTest pTest);
201
202 static void curses_test_start_message_handler(const CU_pTest pTest, const CU_pSuite pSuite);
203 static void curses_test_complete_message_handler(const CU_pTest pTest, const CU_pSuite pSuite,
204 const CU_pFailureRecord pFailure);
205 static void curses_all_tests_complete_message_handler(const CU_pFailureRecord pFailure);
206 static void curses_suite_init_failure_message_handler(const CU_pSuite pSuite);
207
208 static void list_suites(CU_pTestRegistry pRegistry);
209 static void list_tests(CU_pSuite pSuite);
210 static void show_failures(void);
211 static void show_registry_level_help(void);
212 static void show_suite_level_help(CU_pSuite pSuite);
213
214 static void reset_run_parameters(void);
215
216 /*=================================================================
217 * Public Interface functions
218 *=================================================================*/
CU_curses_run_tests(void)219 void CU_curses_run_tests(void)
220 {
221 setvbuf(stdout, NULL, _IONBF, 0);
222 setvbuf(stderr, NULL, _IONBF, 0);
223
224 f_szOptions = _(MAIN_OPTIONS);
225 if (!initialize_windows()) {
226 return;
227 }
228
229 if (!test_initialize()) {
230 goto test_initialize_fail;
231 }
232
233 f_yes_width = strlen(_("Yes"));
234 f_no_width = strlen(_("No"));
235
236 show_detail_window_message(_("Welcome to BCUnit. Press the indicated key to run the command."));
237 curses_registry_level_run(CU_get_registry());
238
239 /* fall thru */
240
241 test_initialize_fail:
242 uninitialize_windows();
243 }
244
245 /*=================================================================
246 * Static function implementation
247 *=================================================================*/
248 /** Initialize the curses interface windows. */
initialize_windows(void)249 static bool initialize_windows(void)
250 {
251 bool bStatus = false;
252
253 if (NULL == (application_windows.pMainWin = initscr())) {
254 goto main_fail;
255 }
256
257 start_color();
258
259 f_nLeft = application_windows.pMainWin->_begx;
260 f_nTop = application_windows.pMainWin->_begy;
261 f_nWidth = application_windows.pMainWin->_maxx;
262 f_nHeight = application_windows.pMainWin->_maxy;
263
264 if (NULL == (application_windows.pTitleWin = newwin(3, f_nWidth, 0, 0))) {
265 goto title_fail;
266 }
267
268 if (NULL == (application_windows.pProgressWin = newwin(2, f_nWidth, 3, 0))) {
269 goto progress_fail;
270 }
271
272 if (NULL == (application_windows.pSummaryWin = newwin(1, f_nWidth, 5, 0))) {
273 goto summary_fail;
274 }
275
276 if (NULL == (application_windows.pRunSummaryWin = newwin(1, f_nWidth, 6, 0))) {
277 goto run_summary_fail;
278 }
279
280 if (NULL == (application_windows.pDetailsWin = newwin(f_nHeight - f_nTop - 7 , f_nWidth, 7, 0))) {
281 goto details_fail;
282 }
283
284 if (NULL == (application_windows.pOptionsWin = newwin(1, f_nWidth, f_nHeight - f_nTop, 0))) {
285 goto option_fail;
286 }
287
288 curs_set(0);
289 noecho();
290 cbreak();
291 keypad(application_windows.pMainWin, CU_TRUE);
292 init_pair(CLEAR_COLOR, COLOR_WHITE, COLOR_BLACK);
293 init_pair(TITLE_COLOR, COLOR_WHITE, COLOR_BLACK);
294 init_pair(PROGRESS_BACKGROUND_COLOR, COLOR_BLACK, COLOR_WHITE);
295 init_pair(PROGRESS_SUCCESS_COLOR, COLOR_WHITE, COLOR_GREEN);
296 init_pair(PROGRESS_FAILURE_COLOR, COLOR_WHITE, COLOR_RED);
297 init_pair(MENU_COLOR, COLOR_GREEN, COLOR_BLACK);
298
299 refresh_windows();
300 bStatus = true;
301 goto main_fail;
302
303 /*
304 * Error Handlers for all the stages.
305 */
306 option_fail:
307 delwin(application_windows.pDetailsWin);
308
309 details_fail:
310 delwin(application_windows.pRunSummaryWin);
311
312 run_summary_fail:
313 delwin(application_windows.pSummaryWin);
314
315 summary_fail:
316 delwin(application_windows.pProgressWin);
317
318 progress_fail:
319 delwin(application_windows.pTitleWin);
320
321 title_fail:
322 endwin();
323
324 main_fail:
325 return bStatus;
326
327 }
328
329 /*------------------------------------------------------------------------*/
330 /** Clean up and delete curses interface windows. */
uninitialize_windows(void)331 static void uninitialize_windows(void)
332 {
333 curs_set(1);
334 echo();
335 nocbreak();
336 keypad(application_windows.pMainWin, CU_FALSE);
337
338 if (details_pad.pPad) {
339 delwin(details_pad.pPad);
340 }
341
342 delwin(application_windows.pOptionsWin);
343 delwin(application_windows.pDetailsWin);
344 delwin(application_windows.pRunSummaryWin);
345 delwin(application_windows.pSummaryWin);
346 delwin(application_windows.pProgressWin);
347 delwin(application_windows.pTitleWin);
348
349 clear();
350 refresh();
351 endwin();
352 }
353
354
355 /*------------------------------------------------------------------------*/
356 /** Refresh curses interface windows. */
refresh_windows(void)357 static void refresh_windows(void)
358 {
359 refresh();
360
361 f_nLeft = application_windows.pMainWin->_begx;
362 f_nTop = application_windows.pMainWin->_begy;
363 f_nWidth = application_windows.pMainWin->_maxx;
364 f_nHeight = application_windows.pMainWin->_maxy;
365
366 refresh_title_window();
367 refresh_progress_window();
368 refresh_run_summary_window();
369 refresh_summary_window();
370 refresh_details_window();
371 refresh_options_window();
372 }
373
374 /*------------------------------------------------------------------------*/
375 /** Refresh the title window. */
refresh_title_window(void)376 static void refresh_title_window(void)
377 {
378 char szPackageTitle[STRING_LENGTH];
379 char* szSite = N_("https://github.com/BelledonneCommunications/bcunit/");
380 static bool bFirstTime = true;
381
382 if (!bFirstTime) {
383 bFirstTime = false;
384 return;
385 }
386
387 snprintf(szPackageTitle, STRING_LENGTH,
388 "%s%s", _("BCUnit - A Unit testing framework for C - Version "), CU_VERSION);
389 wattrset(application_windows.pTitleWin, A_BOLD | COLOR_PAIR(TITLE_COLOR));
390 mvwprintw(application_windows.pTitleWin,
391 0, f_nLeft + (f_nWidth - strlen(szPackageTitle))/2,
392 "%s", szPackageTitle);
393
394 wattrset(application_windows.pTitleWin, A_BOLD | A_UNDERLINE | COLOR_PAIR(TITLE_COLOR));
395 mvwprintw(application_windows.pTitleWin, 1, f_nLeft + (f_nWidth - strlen(_(szSite)))/2,
396 "%s", _(szSite));
397 wattrset(application_windows.pTitleWin, A_NORMAL);
398
399 wrefresh(application_windows.pTitleWin);
400 }
401
402 /*------------------------------------------------------------------------*/
403 /** Refresh the progress bar window. */
refresh_progress_window(void)404 static void refresh_progress_window(void)
405 {
406 wattrset(application_windows.pProgressWin, A_BOLD);
407 mvwprintw(application_windows.pProgressWin, 0, 1, (char *)_(f_szProgress));
408 show_progress_bar();
409 wrefresh(application_windows.pProgressWin);
410 }
411
412 /*------------------------------------------------------------------------*/
413 /** Refresh the summary window. */
refresh_summary_window(void)414 static void refresh_summary_window(void)
415 {
416 char szTemp[STRING_LENGTH];
417
418 memset(szTemp, 0, sizeof(szTemp));
419 snprintf(szTemp, STRING_LENGTH, _("Tests Run : %6u Success : %6u Failed : %6u"),
420 f_uiTestsRun, f_uiTestsRunSuccessful,
421 f_uiTestsRun - f_uiTestsRunSuccessful);
422 werase(application_windows.pSummaryWin);
423 mvwprintw(application_windows.pSummaryWin, 0, 1, "%s", szTemp);
424 wrefresh(application_windows.pSummaryWin);
425 }
426
427 /*------------------------------------------------------------------------*/
428 /** Prints a custom message in the detail window. */
show_detail_window_message(const char * msg)429 static void show_detail_window_message(const char *msg)
430 {
431 if (NULL != msg) {
432
433 if (!create_pad(&details_pad, application_windows.pDetailsWin, 1, 256)) {
434 return;
435 }
436
437 assert(256 >= strlen(msg));
438 mvwprintw(details_pad.pPad, 0, 0, "%s", msg);
439 refresh_details_window();
440 }
441 }
442
443 /*------------------------------------------------------------------------*/
444 /** Refresh the run summary window. */
refresh_run_summary_window(void)445 static void refresh_run_summary_window(void)
446 {
447 const char* szRunSummary = N_("Running test \'%s\' of Suite \'%s\'");
448 char szTemp[STRING_LENGTH];
449
450 if (f_pCurrentTest && f_pCurrentSuite) {
451 assert(NULL != f_pCurrentTest->pName);
452 assert(NULL != f_pCurrentSuite->pName);
453 snprintf(szTemp, STRING_LENGTH, _(szRunSummary),
454 f_pCurrentTest->pName, f_pCurrentSuite->pName);
455 }
456 else {
457 snprintf(szTemp, STRING_LENGTH, "%s", "");
458 }
459 werase(application_windows.pRunSummaryWin);
460 mvwprintw(application_windows.pRunSummaryWin, 0, 1, "%s", szTemp);
461 wrefresh(application_windows.pRunSummaryWin);
462 }
463
464 /*------------------------------------------------------------------------*/
465 /** Refresh the details window. */
refresh_details_window(void)466 static void refresh_details_window(void)
467 {
468 const char* szDetailsTitle = N_(" Details Window ");
469
470 box(application_windows.pDetailsWin, ACS_VLINE, ACS_HLINE);
471 mvwprintw(application_windows.pDetailsWin, 0,
472 f_nLeft + (f_nWidth - strlen(_(szDetailsTitle)))/2, "%s", _(szDetailsTitle));
473 scrollok(application_windows.pDetailsWin, CU_TRUE);
474 wrefresh(application_windows.pDetailsWin);
475
476 if (details_pad.pPad) {
477 prefresh(details_pad.pPad, details_pad.uiPadRow, details_pad.uiPadCol,
478 details_pad.uiWinTop, details_pad.uiWinLeft,
479 details_pad.uiWinTop + details_pad.uiWinRows,
480 details_pad.uiWinLeft + details_pad.uiWinColumns);
481 }
482 }
483
484 /*------------------------------------------------------------------------*/
485 /** Refresh the options window. */
refresh_options_window(void)486 static void refresh_options_window(void)
487 {
488 int nPos = 0;
489 const char* szHotKey = NULL;
490
491 wclear(application_windows.pOptionsWin);
492 mvwprintw(application_windows.pOptionsWin, 0, 1, "%s", f_szOptions);
493
494 get_hotkey(f_szOptions, NULL);
495 wattron(application_windows.pOptionsWin, A_BOLD);
496 while (NULL != (szHotKey = get_hotkey((const char*)NULL, &nPos))) {
497 mvwaddstr(application_windows.pOptionsWin, 0, nPos + 1, szHotKey);
498 }
499 wattroff(application_windows.pOptionsWin, A_BOLD);
500
501 wrefresh(application_windows.pOptionsWin);
502 }
503
504 /*------------------------------------------------------------------------*/
505 /** Show the progress bar window. */
show_progress_bar(void)506 static void show_progress_bar(void)
507 {
508 int nLength = 0;
509 int nIndex = 0;
510 int nStart = strlen(_(f_szProgress));
511 int nColorID = 0;
512
513 if (0 == (f_uiTestsRun + f_uiTestsSkipped)) {
514 nLength = f_nWidth - f_nLeft - nStart - 6;
515 nColorID = PROGRESS_BACKGROUND_COLOR;
516 }
517 else {
518 nLength = (f_nWidth - f_nLeft - nStart - 6) * ((double)(f_uiTestsRun + f_uiTestsSkipped) / f_uiTotalTests);
519 nColorID = (!f_uiTestsSkipped && f_uiTestsRun == f_uiTestsRunSuccessful)
520 ? PROGRESS_SUCCESS_COLOR
521 : PROGRESS_FAILURE_COLOR;
522 }
523
524 wattron(application_windows.pProgressWin, A_BOLD | COLOR_PAIR(nColorID));
525 for (nIndex = 0; nIndex < nLength; nIndex++) {
526 mvwprintw(application_windows.pProgressWin, 0, nStart + nIndex, " ");
527 }
528 wattroff(application_windows.pProgressWin, COLOR_PAIR(nColorID));
529 }
530
531 /*------------------------------------------------------------------------*/
532 /** Initialize the message handlers in preparation for running tests. */
test_initialize(void)533 static bool test_initialize(void)
534 {
535 if (NULL == CU_get_registry()) {
536 return false;
537 }
538
539 CU_set_test_start_handler(curses_test_start_message_handler);
540 CU_set_test_complete_handler(curses_test_complete_message_handler);
541 CU_set_all_test_complete_handler(curses_all_tests_complete_message_handler);
542 CU_set_suite_init_failure_handler(curses_suite_init_failure_message_handler);
543 return true;
544 }
545
546 /*------------------------------------------------------------------------*/
547 /** Parse a string and return the coded hotkeys.
548 * If called with szStr non-NULL, the string is simply stored.
549 * Subsequent calls with szStr NULL will cause the
550 * hotkeys in the string (chars between parentheses) to
551 * be returned sequentially in the order in which they
552 * appear in the original string.
553 * @param szStr String to parse (non-NULL to set, NULL to parse).
554 * @param pPos Used to store position of the next '('.
555 * @return If szStr is non-NULL, it is returned. If szStr is NULL,
556 * the next hotkey character is returned, or NULL if there
557 * are no more hotkey characters in the original string.
558 */
get_hotkey(const char * szStr,int * pPos)559 static const char* get_hotkey(const char* szStr, int* pPos)
560 {
561 static char szTemp[128] = "";
562 static char szString[128] = "";
563 static int nPos = 0;
564
565 int nTempIndex;
566 char* pS = NULL;
567
568 if (szStr) {
569 nPos = 0;
570 strcpy(szString, szStr);
571 return szString;
572 }
573
574 memset(szTemp, 0, sizeof(szTemp));
575 for (nTempIndex = 0, pS = szString + nPos; *pS; nPos++, pS++) {
576 if (!nTempIndex && '(' == *pS) {
577 szTemp[nTempIndex++] = *pS;
578 *pPos = nPos;
579 }
580 else if (nTempIndex && ')' == *pS) {
581 szTemp[nTempIndex++] = *pS;
582 szTemp[nTempIndex++] = '\0';
583 return szTemp;
584 }
585 else if (nTempIndex) {
586 szTemp[nTempIndex++] = *pS;
587 }
588 }
589
590 return NULL;
591 }
592
593 /*------------------------------------------------------------------------*/
594 /**
595 * Main loop for curses interface.
596 * Displays actions and responds based on user imput.
597 * @param pRegistry The CU_pTestRegistry to use for testing.
598 * If NULL, uses the default registry.
599 */
curses_registry_level_run(CU_pTestRegistry pRegistry)600 static STATUS curses_registry_level_run(CU_pTestRegistry pRegistry)
601 {
602 char szSuiteNumber[STRING_LENGTH];
603 CU_pSuite pSuite = NULL;
604 bool bContinue = true;
605 char szTemp[STRING_LENGTH];
606 long suite_num;
607
608 if (NULL == pRegistry) {
609 pRegistry = CU_get_registry();
610 }
611 assert(NULL != pRegistry);
612
613 while (bContinue) {
614 int option = toupper(getch());
615
616 if (option == _("R")[0]) {
617 curses_run_all_tests(pRegistry);
618 }
619
620 else if (option == _("S")[0]) {
621 if (0 == pRegistry->uiNumberOfSuites) {
622 fprintf(stdout, "\n%s", _("No suites are registered."));
623 }
624 else {
625 list_suites(pRegistry);
626 snprintf(szTemp, STRING_LENGTH, _("Enter number of suite to select (1-%u) : "),
627 pRegistry->uiNumberOfSuites);
628 read_input_string(szTemp, szSuiteNumber, STRING_LENGTH);
629 refresh_details_window();
630 suite_num = atol(szSuiteNumber);
631 pSuite = CU_get_suite_by_index(suite_num, pRegistry);
632 if (NULL != pSuite) {
633 assert(NULL != pSuite->pName);
634 snprintf(szTemp, STRING_LENGTH, _("Suite '%s' selected."), pSuite->pName);
635 show_detail_window_message(szTemp);
636 if (STOP == curses_suite_level_run(pSuite)) {
637 bContinue = false;
638 }
639 f_szOptions = _(MAIN_OPTIONS);
640 refresh_options_window();
641 }
642 else {
643 show_detail_window_message(_("Suite not found."));
644 }
645 }
646 }
647
648 else if (option == _("L")[0]) {
649 list_suites(pRegistry);
650 }
651
652 else if (option == _("A")[0]) {
653 if (0 == pRegistry->uiNumberOfSuites) {
654 fprintf(stdout, "\n%s", _("No suites are registered."));
655 }
656 else {
657 while (1) {
658 list_suites(pRegistry);
659 snprintf(szTemp, STRING_LENGTH, _("Enter number of suite to select (1-%u) : "),
660 pRegistry->uiNumberOfSuites);
661 read_input_string(szTemp, szSuiteNumber, STRING_LENGTH);
662 refresh_details_window();
663 suite_num = atol(szSuiteNumber);
664 pSuite = CU_get_suite_by_index(suite_num, pRegistry);
665 if (NULL != pSuite) {
666 CU_set_suite_active(pSuite, (CU_FALSE == pSuite->fActive) ? CU_TRUE : CU_FALSE);
667 }
668 else {
669 break;
670 }
671 }
672 f_szOptions = _(MAIN_OPTIONS);
673 refresh_options_window();
674 }
675 }
676
677 else if (option == _("F")[0]) {
678 show_failures();
679 }
680
681 else if (option == _("O")[0]) {
682 curses_set_options_run();
683 }
684
685 else if (option == _("Q")[0]) {
686 return bContinue = false;
687 }
688
689 else if ((option == KEY_UP) ||
690 (option == KEY_DOWN) ||
691 (option == KEY_RIGHT) ||
692 (option == KEY_LEFT)) {
693 scroll_window(option, &details_pad, refresh_details_window);
694 }
695
696 else if ((option == _("H")[0]) || (option == _("?")[0])) {
697 show_registry_level_help();
698 }
699 }
700
701 return STOP;
702 }
703
704 /*------------------------------------------------------------------------*/
705 /** Run a selected suite within the curses interface.
706 * Displays actions and responds based on user imput.
707 * @param pSuite The suite to use for testing (non-NULL).
708 */
curses_suite_level_run(CU_pSuite pSuite)709 static STATUS curses_suite_level_run(CU_pSuite pSuite)
710 {
711 char szTestNumber[STRING_LENGTH];
712 char szTemp[STRING_LENGTH];
713 CU_pTestRegistry pRegistry = CU_get_registry();
714 CU_pTest pTest = NULL;
715 long test_num;
716
717 assert(NULL != pRegistry);
718 assert(NULL != pSuite);
719 assert(NULL != pSuite->pName);
720
721 f_szOptions = _(SUITE_OPTIONS);
722 refresh_options_window();
723
724 while (true) {
725 int option = toupper(getch());
726
727 if (option == _("R")[0]) {
728 curses_run_suite_tests(pSuite);
729 }
730
731 else if (option == _("S")[0]) {
732 if (0 == pSuite->uiNumberOfTests) {
733 snprintf(szTemp, STRING_LENGTH,
734 _("Suite %s contains no tests."), pSuite->pName);
735 show_detail_window_message(szTemp);
736 }
737 else {
738 list_tests(pSuite);
739 snprintf(szTemp, STRING_LENGTH, "%s",
740 _("Enter number of test to select (1-%u) : "),
741 pRegistry->uiNumberOfSuites);
742 read_input_string(szTemp, szTestNumber, STRING_LENGTH);
743 test_num = atol(szTestNumber);
744 pTest = CU_get_test_by_index(test_num, pSuite);
745 if (NULL != pTest) {
746 curses_run_single_test(pSuite, pTest);
747 }
748 else {
749 show_detail_window_message(_("Test not found."));
750 }
751 refresh_details_window();
752 }
753 }
754
755 else if (option == _("L")[0]) {
756 list_tests(pSuite);
757 }
758
759 else if (option == _("F")[0]) {
760 show_failures();
761 }
762
763 else if (option == _("A")[0]) {
764 if (0 == pSuite->uiNumberOfTests) {
765 snprintf(szTemp, STRING_LENGTH,
766 _("Suite %s contains no tests."), pSuite->pName);
767 show_detail_window_message(szTemp);
768 }
769 else {
770 while (1) {
771 list_tests(pSuite);
772 snprintf(szTemp, STRING_LENGTH, "%s",
773 _("Enter number of test to select (1-%u) : "),
774 pRegistry->uiNumberOfSuites);
775 read_input_string(szTemp, szTestNumber, STRING_LENGTH);
776 test_num = atol(szTestNumber);
777 pTest = CU_get_test_by_index(test_num, pSuite);
778 if (NULL != pTest) {
779 CU_set_test_active(pTest, (CU_FALSE == pTest->fActive) ? CU_TRUE : CU_FALSE);
780 }
781 else {
782 break;
783 }
784 }
785 f_szOptions = _(SUITE_OPTIONS);
786 refresh_options_window();
787 }
788 }
789
790 else if (option == _("O")[0]) {
791 curses_set_options_run();
792 }
793
794 else if (option == _("U")[0]) {
795 return CONTINUE;
796 }
797
798 else if (option == _("Q")[0]) {
799 return STOP;
800 }
801
802 else if ((option == KEY_UP) ||
803 (option == KEY_DOWN) ||
804 (option == KEY_RIGHT) ||
805 (option == KEY_LEFT)) {
806 scroll_window(option, &details_pad, refresh_details_window);
807 }
808
809 else if ((option == _("H")[0]) || (option == _("?")[0])) {
810 show_suite_level_help(pSuite);
811 }
812 }
813
814 return CONTINUE;
815 }
816
817 /*------------------------------------------------------------------------*/
818 /** Display a prompt, then read a string from the keyboard.
819 * @param szPrompt The prompt to display.
820 * @param szValue The string in which to store the response.
821 * @param nBytes The length of the szValue buffer.
822 */
read_input_string(const char szPrompt[],char szValue[],int nBytes)823 static void read_input_string(const char szPrompt[], char szValue[], int nBytes)
824 {
825 echo();
826 curs_set(1);
827 nocbreak();
828
829 wclear(application_windows.pOptionsWin);
830 mvwprintw(application_windows.pOptionsWin, 0, 1, "%s", szPrompt);
831 wgetnstr(application_windows.pOptionsWin, szValue, nBytes - 1);
832 refresh_options_window();
833
834 cbreak();
835 curs_set(0);
836 noecho();
837 }
838
839 /*------------------------------------------------------------------------*/
840 /** Scroll a window.
841 * @param nCommand Code for the direction to scroll.
842 * @param pPad The window to scroll.
843 * @param parent_refresh Function to call to refresh the parent window.
844 */
scroll_window(int nCommand,APPPAD * pPad,void (* parent_refresh)(void))845 static void scroll_window(int nCommand, APPPAD* pPad, void (*parent_refresh)(void))
846 {
847 if (NULL == pPad->pPad) {
848 return;
849 }
850
851 switch (nCommand) {
852 case KEY_UP:
853 if (pPad->uiPadRow) {
854 --pPad->uiPadRow;
855 (*parent_refresh)();
856 }
857 break;
858
859 case KEY_DOWN:
860 if (pPad->uiRows - 1 > pPad->uiPadRow + pPad->uiWinRows) {
861 ++pPad->uiPadRow;
862 (*parent_refresh)();
863 }
864 break;
865
866 case KEY_LEFT:
867 if (pPad->uiPadCol) {
868 --pPad->uiPadCol;
869 (*parent_refresh)();
870 }
871 break;
872
873 case KEY_RIGHT:
874 if (details_pad.uiColumns - 1 > details_pad.uiPadCol + details_pad.uiWinColumns) {
875 ++pPad->uiPadCol;
876 (*parent_refresh)();
877 }
878 break;
879
880 default:
881 break;
882 }
883 }
884
885 /*------------------------------------------------------------------------*/
886 /** Create a window having specified parent and dimensions.
887 * @param pPad Pointer to the new window.
888 * @param pParent Parent window.
889 * @param uiRows Number of rows for new window.
890 * @param uiCols Number of columnss for new window.
891 */
create_pad(APPPAD * pPad,WINDOW * pParent,unsigned int uiRows,unsigned int uiCols)892 static bool create_pad(APPPAD* pPad, WINDOW* pParent, unsigned int uiRows,
893 unsigned int uiCols)
894 {
895 bool bStatus = false;
896
897 assert(pParent);
898 if (pPad->pPad) {
899 delwin(pPad->pPad);
900 }
901
902 if (NULL != pPad && NULL == (pPad->pPad = newpad(uiRows, uiCols))) {
903 goto newpad_fail;
904 }
905
906 pPad->uiRows = uiRows;
907 pPad->uiColumns = uiCols;
908 pPad->uiPadRow = 0;
909 pPad->uiPadCol = 0;
910 pPad->uiWinLeft = application_windows.pDetailsWin->_begx + 1;
911 pPad->uiWinTop = application_windows.pDetailsWin->_begy + 1;
912 pPad->uiWinColumns = application_windows.pDetailsWin->_maxx - 2;
913 pPad->uiWinRows = application_windows.pDetailsWin->_maxy - 2;
914
915 bStatus = true;
916
917 newpad_fail:
918 return bStatus;
919 }
920
921 /*------------------------------------------------------------------------*/
922 /** Prints help text for registry level to detail window. */
show_registry_level_help(void)923 static void show_registry_level_help(void)
924 {
925 if (!create_pad(&details_pad, application_windows.pDetailsWin, 8, 256)) {
926 return;
927 }
928
929 mvwprintw(details_pad.pPad, 0, 0, _("Commands: R - run all tests in all suites"));
930 mvwprintw(details_pad.pPad, 1, 0, _(" S - Select a suite to run or modify"));
931 mvwprintw(details_pad.pPad, 2, 0, _(" L - List all registered suites"));
932 mvwprintw(details_pad.pPad, 3, 0, _(" A - Activate or deactivate a suite (toggle)"));
933 mvwprintw(details_pad.pPad, 4, 0, _(" F - Show failures from last test run"));
934 mvwprintw(details_pad.pPad, 5, 0, _(" O - Set BCUnit options"));
935 mvwprintw(details_pad.pPad, 6, 0, _(" H - Show this help message"));
936 mvwprintw(details_pad.pPad, 7, 0, _(" Q - Quit the application"));
937 refresh_details_window();
938 }
939
940 /*------------------------------------------------------------------------*/
941 /** Prints help text for suite level to detail window. */
show_suite_level_help(CU_pSuite pSuite)942 static void show_suite_level_help(CU_pSuite pSuite)
943 {
944 char szTemp[STRING_LENGTH];
945
946 assert(NULL != pSuite);
947 assert(NULL != pSuite->pName);
948
949 if (!create_pad(&details_pad, application_windows.pDetailsWin, 9, 256)) {
950 return;
951 }
952
953 snprintf(szTemp, STRING_LENGTH, _("Commands: R - run all tests in suite %s"),
954 pSuite->pName);
955 mvwprintw(details_pad.pPad, 0, 0, szTemp);
956 mvwprintw(details_pad.pPad, 1, 0, _(" S - Select and run a test"));
957 snprintf(szTemp, STRING_LENGTH, _(" L - List all tests registered in suite %s"),
958 pSuite->pName);
959 mvwprintw(details_pad.pPad, 2, 0, szTemp);
960 mvwprintw(details_pad.pPad, 3, 0, _(" A - Activate or deactivate a test (toggle)"));
961 mvwprintw(details_pad.pPad, 4, 0, _(" F - Show failures from last test run"));
962 mvwprintw(details_pad.pPad, 5, 0, _(" M - Move up to main menu"));
963 mvwprintw(details_pad.pPad, 6, 0, _(" O - Set BCUnit options"));
964 mvwprintw(details_pad.pPad, 7, 0, _(" H - Show this help message"));
965 mvwprintw(details_pad.pPad, 8, 0, _(" Q - Quit the application"));
966 refresh_details_window();
967 }
968
969 /*------------------------------------------------------------------------*/
970 /** Print a list of registered suites to the detail window.
971 * @param pRegistry The CU_pTestRegistry to query (non-NULL).
972 */
list_suites(CU_pTestRegistry pRegistry)973 static void list_suites(CU_pTestRegistry pRegistry)
974 {
975
976 CU_pSuite pCurSuite = NULL;
977 int i;
978 char szTemp[STRING_LENGTH];
979 static size_t width[6];
980
981 if (NULL == pRegistry) {
982 pRegistry = CU_get_registry();
983 }
984
985 assert(pRegistry);
986
987 if (0 == pRegistry->uiNumberOfSuites) {
988 show_detail_window_message(_("No suites are registered."));
989 return;
990 }
991
992 assert(pRegistry->pSuite);
993
994 if (!create_pad(&details_pad, application_windows.pDetailsWin, pRegistry->uiNumberOfSuites + 4, 256)) {
995 return;
996 }
997
998 /* only need to calculate formatting widths once */
999 if (0 == width[0]) {
1000 width[0] = CU_number_width(pRegistry->uiNumberOfSuites) + 1;
1001 width[1] = 34;
1002 width[2] = CU_MAX(strlen(_("Init?")), CU_MAX(f_yes_width, f_no_width)) + 1;
1003 width[3] = CU_MAX(strlen(_("Cleanup?")), CU_MAX(f_yes_width, f_no_width)) + 1;
1004 width[4] = CU_MAX(strlen(_("#Tests")), CU_number_width(pRegistry->uiNumberOfTests) + 1) + 1;
1005 width[5] = CU_MAX(strlen(_("Active?")), CU_MAX(f_yes_width, f_no_width)) + 1;
1006 }
1007
1008 snprintf(szTemp, STRING_LENGTH, "%*s %-*s%*s%*s%*s%*s",
1009 width[0], _("#"),
1010 width[1], _("Suite Name"),
1011 width[2], _("Init?"),
1012 width[3], _("Cleanup?"),
1013 width[4], _("#Tests"),
1014 width[5], _("Active?"));
1015 mvwprintw(details_pad.pPad, 0, 0, "%s", szTemp);
1016
1017 for (i = 0, pCurSuite = pRegistry->pSuite; pCurSuite; pCurSuite = pCurSuite->pNext, i++) {
1018 assert(NULL != pCurSuite->pName);
1019 snprintf(szTemp, STRING_LENGTH, "%*d. %-*.*s%*s%*s%*u%*s",
1020 width[0], i+1,
1021 width[1], width[1] - 1, pCurSuite->pName,
1022 width[2]-1, (NULL != pCurSuite->pInitializeFunc) ? _("Yes") : _("No"),
1023 width[3], (NULL != pCurSuite->pCleanupFunc) ? _("Yes") : _("No"),
1024 width[4], pCurSuite->uiNumberOfTests,
1025 width[5], (CU_FALSE != pCurSuite->fActive) ? _("Yes") : _("No"));
1026 mvwprintw(details_pad.pPad, i + 2, 0, "%s", szTemp);
1027 }
1028
1029 mvwprintw(details_pad.pPad, i + 2, 0, "%s",
1030 "---------------------------------------------------------------------------");
1031 mvwprintw(details_pad.pPad, i + 3, 0,
1032 _("Total Number of Suites : %-u"), pRegistry->uiNumberOfSuites);
1033 refresh_details_window();
1034 }
1035
1036 /*------------------------------------------------------------------------*/
1037 /** Print a list of tests contained in a specified suite to the detail window.
1038 * @param pSuite The suite to query (non-NULL).
1039 */
list_tests(CU_pSuite pSuite)1040 static void list_tests(CU_pSuite pSuite)
1041 {
1042 CU_pTest pCurTest = NULL;
1043 unsigned int i;
1044 char szTemp[STRING_LENGTH];
1045 static size_t width[3];
1046
1047 assert(NULL != pSuite);
1048 assert(NULL != pSuite->pName);
1049
1050 if (!create_pad(&details_pad, application_windows.pDetailsWin, pSuite->uiNumberOfTests + 5, 256)) {
1051 return;
1052 }
1053
1054 if (0 == pSuite->uiNumberOfTests) {
1055 snprintf(szTemp, STRING_LENGTH,
1056 _("Suite %s contains no tests."), pSuite->pName);
1057 show_detail_window_message(szTemp);
1058 return;
1059 }
1060
1061 assert(pSuite->pTest);
1062
1063 /* only number of tests can change between calls */
1064 width[0] = CU_number_width(pSuite->uiNumberOfTests) + 1;
1065 if (0 == width[1]) {
1066 width[1] = 34;
1067 width[2] = CU_MAX(strlen(_("Active?")), CU_MAX(f_yes_width, f_no_width)) + 1;
1068 }
1069
1070 snprintf(szTemp, STRING_LENGTH, "%s: %s", _("Suite"), pSuite->pName);
1071 mvwprintw(details_pad.pPad, 0, 0, szTemp);
1072
1073 snprintf(szTemp, STRING_LENGTH,
1074 "%*s %-*s%*s",
1075 width[0], _("#"),
1076 width[1], _("Test Name"),
1077 width[2], _("Active?"));
1078 mvwprintw(details_pad.pPad, 1, 0, szTemp);
1079
1080 for (i = 0, pCurTest = pSuite->pTest ;
1081 NULL != pCurTest ;
1082 pCurTest = pCurTest->pNext, i++) {
1083 assert(NULL != pCurTest->pName);
1084 snprintf(szTemp, STRING_LENGTH,
1085 "%*u. %-*.*s%*s",
1086 width[0], i + 1,
1087 width[1], width[1]-1, pCurTest->pName,
1088 width[2]-1, (CU_FALSE != pCurTest->fActive) ? _("Yes") : _("No"));
1089 mvwprintw(details_pad.pPad, i + 3, 0, "%s", szTemp);
1090 }
1091
1092 mvwprintw(details_pad.pPad, i + 3, 0, "%s",
1093 "---------------------------------------------");
1094 mvwprintw(details_pad.pPad, i + 4, 0,
1095 _("Total Number of Tests : %-u"), pSuite->uiNumberOfTests);
1096 refresh_details_window();
1097 }
1098
1099 /*------------------------------------------------------------------------*/
1100 /** Display the record of test failures in the detail window. */
show_failures(void)1101 static void show_failures(void)
1102 {
1103 int i;
1104 CU_pFailureRecord pFailure = CU_get_failure_list();
1105 unsigned int nFailures = CU_get_number_of_failure_records();
1106
1107 if (0 == nFailures) {
1108 show_detail_window_message(_("No failures."));
1109 return;
1110 }
1111
1112 assert(pFailure);
1113
1114 if (!create_pad(&details_pad, application_windows.pDetailsWin, nFailures + 5, 256)) {
1115 return;
1116 }
1117
1118 mvwprintw(details_pad.pPad, 1, 0, "%s", _(" src_file:line# : (suite:test) : failure_condition"));
1119
1120 for (i = 0 ; pFailure ; pFailure = pFailure->pNext, i++) {
1121 char szTemp[STRING_LENGTH];
1122
1123 snprintf(szTemp, STRING_LENGTH, "%d. %s:%d : (%s : %s) : %s", i + 1,
1124 ((NULL != pFailure->strFileName) ? pFailure->strFileName : ""),
1125 pFailure->uiLineNumber,
1126 (((NULL != pFailure->pSuite) && (NULL != pFailure->pSuite->pName))
1127 ? pFailure->pSuite->pName : ""),
1128 (((NULL != pFailure->pTest) && (NULL != pFailure->pTest->pName))
1129 ? pFailure->pTest->pName : ""),
1130 ((NULL != pFailure->strCondition) ? pFailure->strCondition : ""));
1131
1132 mvwprintw(details_pad.pPad, i + 3, 0, "%s", szTemp);
1133 }
1134
1135 mvwprintw(details_pad.pPad, i + 3, 0, "%s", "=============================================");
1136 mvwprintw(details_pad.pPad, i + 4, 0, _("Total Number of Failures : %-u"), nFailures);
1137 refresh_details_window();
1138 }
1139
1140 /*------------------------------------------------------------------------*/
1141 /**
1142 * Sets BCUnit options interactively using curses interface.
1143 * Displays actions and responds based on user imput.
1144 */
curses_set_options_run(void)1145 static STATUS curses_set_options_run(void)
1146 {
1147 char szTemp[STRING_LENGTH];
1148 STATUS eStatus = CONTINUE;
1149 long option_num;
1150
1151 if (!create_pad(&details_pad, application_windows.pDetailsWin, 3, 256)) {
1152 return eStatus;
1153 }
1154
1155 mvwprintw(details_pad.pPad, 0, 0, _("BCUnit Options:"));
1156
1157 while (CONTINUE == eStatus) {
1158
1159 snprintf(szTemp, STRING_LENGTH, _(" 1 - Inactive suites/tests treated as runtime failures %s"),
1160 (CU_FALSE != CU_get_fail_on_inactive()) ? _("Yes") : _("No "));
1161 mvwprintw(details_pad.pPad, 2, 0, szTemp);
1162 refresh_details_window();
1163 read_input_string(_("Enter number of option to change : "), szTemp, STRING_LENGTH);
1164 option_num = atol(szTemp);
1165
1166 switch (option_num) {
1167 case 1:
1168 CU_set_fail_on_inactive((CU_FALSE == CU_get_fail_on_inactive()) ? CU_TRUE : CU_FALSE);
1169 break;
1170
1171 default:
1172 eStatus = MOVE_UP;
1173 break;
1174 }
1175 }
1176 return eStatus;
1177 }
1178
1179 /*------------------------------------------------------------------------*/
1180 /** Run all tests within the curses interface.
1181 * The test registry is changed to the specified registry
1182 * before running the tests, and reset to the original
1183 * registry when done.
1184 * @param pRegistry The CU_pTestRegistry containing the tests
1185 * to be run (non-NULL).
1186 * @return An error code indicating the error status
1187 * during the test run.
1188 */
curses_run_all_tests(CU_pTestRegistry pRegistry)1189 static CU_ErrorCode curses_run_all_tests(CU_pTestRegistry pRegistry)
1190 {
1191 CU_pTestRegistry pOldRegistry = NULL;
1192 CU_ErrorCode result;
1193
1194 assert(pRegistry);
1195
1196 reset_run_parameters();
1197 f_uiTotalTests = pRegistry->uiNumberOfTests;
1198 f_uiTotalSuites = pRegistry->uiNumberOfSuites;
1199
1200 if (NULL != pRegistry) {
1201 pOldRegistry = CU_set_registry(pRegistry);
1202 }
1203 result = CU_run_all_tests();
1204 if (NULL != pOldRegistry) {
1205 CU_set_registry(pOldRegistry);
1206 }
1207 return result;
1208 }
1209
1210 /*------------------------------------------------------------------------*/
1211 /** Run a specified suite within the curses interface.
1212 * @param pSuite The suite to be run (non-NULL).
1213 * @return An error code indicating the error status
1214 * during the test run.
1215 */
curses_run_suite_tests(CU_pSuite pSuite)1216 static CU_ErrorCode curses_run_suite_tests(CU_pSuite pSuite)
1217 {
1218 reset_run_parameters();
1219 f_uiTotalTests = pSuite->uiNumberOfTests;
1220 f_uiTotalSuites = 1;
1221 return CU_run_suite(pSuite);
1222 }
1223
1224 /*------------------------------------------------------------------------*/
1225 /** Run a specific test for the specified suite within
1226 * the curses interface.
1227 * @param pSuite The suite containing the test to be run (non-NULL).
1228 * @param pTest The test to be run (non-NULL).
1229 * @return An error code indicating the error status
1230 * during the test run.
1231 */
curses_run_single_test(CU_pSuite pSuite,CU_pTest pTest)1232 static CU_ErrorCode curses_run_single_test(CU_pSuite pSuite, CU_pTest pTest)
1233 {
1234 reset_run_parameters();
1235 f_uiTotalTests = 1;
1236 f_uiTotalSuites = 1;
1237 return CU_run_test(pSuite, pTest);
1238 }
1239
1240 /*------------------------------------------------------------------------*/
1241 /** Reset the local run counters and prepare for a test run. */
reset_run_parameters(void)1242 static void reset_run_parameters(void)
1243 {
1244 f_pCurrentTest = NULL;
1245 f_pCurrentSuite = NULL;
1246 f_uiTestsRunSuccessful = f_uiTestsRun = f_uiTotalTests = f_uiTestsFailed = f_uiTestsSkipped = 0;
1247 f_uiTotalSuites = f_uiSuitesSkipped = 0;
1248 refresh_progress_window();
1249 refresh_summary_window();
1250 refresh_run_summary_window();
1251 }
1252
1253 /*------------------------------------------------------------------------*/
1254 /** Handler function called at start of each test.
1255 * @param pTest The test being run.
1256 * @param pSuite The suite containing the test.
1257 */
curses_test_start_message_handler(const CU_pTest pTest,const CU_pSuite pSuite)1258 static void curses_test_start_message_handler(const CU_pTest pTest, const CU_pSuite pSuite)
1259 {
1260 f_pCurrentTest = (CU_pTest)pTest;
1261 f_pCurrentSuite = (CU_pSuite)pSuite;
1262 refresh_run_summary_window();
1263 }
1264
1265 /*------------------------------------------------------------------------*/
1266 /** Handler function called at completion of each test.
1267 * @param pTest The test being run.
1268 * @param pSuite The suite containing the test.
1269 * @param pFailure Pointer to the 1st failure record for this test.
1270 */
curses_test_complete_message_handler(const CU_pTest pTest,const CU_pSuite pSuite,const CU_pFailureRecord pFailure)1271 static void curses_test_complete_message_handler(const CU_pTest pTest,
1272 const CU_pSuite pSuite,
1273 const CU_pFailureRecord pFailure)
1274 {
1275 /* Not used in curses implementation - quiet compiler warning */
1276 CU_UNREFERENCED_PARAMETER(pTest);
1277 CU_UNREFERENCED_PARAMETER(pSuite);
1278 CU_UNREFERENCED_PARAMETER(pFailure);
1279
1280 f_uiTestsRun++;
1281 if (CU_get_number_of_tests_failed() != f_uiTestsFailed) {
1282 f_uiTestsFailed++;
1283 }
1284 else {
1285 f_uiTestsRunSuccessful++;
1286 }
1287
1288 refresh_summary_window();
1289 refresh_progress_window();
1290 }
1291
1292 /*------------------------------------------------------------------------*/
1293 /** Handler function called at completion of all tests in a suite.
1294 * @param pFailure Pointer to the test failure record list.
1295 */
curses_all_tests_complete_message_handler(const CU_pFailureRecord pFailure)1296 static void curses_all_tests_complete_message_handler(const CU_pFailureRecord pFailure)
1297 {
1298 /* Not used in curses implementation - quiet compiler warning */
1299 CU_UNREFERENCED_PARAMETER(pFailure);
1300
1301 f_pCurrentTest = NULL;
1302 f_pCurrentSuite = NULL;
1303
1304 if (!create_pad(&details_pad, application_windows.pDetailsWin, 21, 256)) {
1305 return;
1306 }
1307
1308 mvwprintw(details_pad.pPad, 0, 0, "%s", _("====== Suite Run Summary ======"));
1309 mvwprintw(details_pad.pPad, 1, 0, _(" TOTAL SUITES: %4u"), f_uiTotalSuites);
1310 mvwprintw(details_pad.pPad, 2, 0, _(" Run: %4u"), f_uiTotalSuites - f_uiSuitesSkipped);
1311 mvwprintw(details_pad.pPad, 3, 0, _(" Skipped: %4u"), f_uiSuitesSkipped);
1312 mvwprintw(details_pad.pPad, 4, 0, _(" Inactive: %4u"), CU_get_number_of_suites_inactive());
1313
1314 mvwprintw(details_pad.pPad, 6, 0, "%s", _("====== Test Run Summary ======="));
1315 mvwprintw(details_pad.pPad, 7, 0, _(" TOTAL TESTS: %4u"), f_uiTotalTests);
1316 mvwprintw(details_pad.pPad, 8, 0, _(" Run: %4u"), f_uiTestsRun);
1317 mvwprintw(details_pad.pPad, 9, 0, _(" Skipped: %4u"), f_uiTestsSkipped);
1318 mvwprintw(details_pad.pPad, 10, 0, _(" Successful: %4u"), f_uiTestsRunSuccessful);
1319 mvwprintw(details_pad.pPad, 11, 0, _(" Failed: %4u"), f_uiTestsFailed);
1320 mvwprintw(details_pad.pPad, 12, 0, _(" Inactive: %4u"), CU_get_number_of_tests_inactive());
1321
1322 mvwprintw(details_pad.pPad, 14, 0, "%s", _("====== Assertion Summary ======"));
1323 mvwprintw(details_pad.pPad, 15, 0, _(" TOTAL ASSERTS: %4u"), CU_get_number_of_asserts());
1324 mvwprintw(details_pad.pPad, 16, 0, _(" Passed: %4u"), CU_get_number_of_successes());
1325 mvwprintw(details_pad.pPad, 17, 0, _(" Failed: %4u"), CU_get_number_of_failures());
1326
1327
1328 mvwprintw(details_pad.pPad, 19, 0, "%s", _("====== Failure Summary ======"));
1329 mvwprintw(details_pad.pPad, 20, 0, _(" TOTAL FAILURES: %4u"), CU_get_number_of_failure_records());
1330
1331 refresh_details_window();
1332 refresh_run_summary_window();
1333 }
1334
1335 /*------------------------------------------------------------------------*/
1336 /** Handler function called when suite initialization fails.
1337 * @param pSuite The suite for which initialization failed.
1338 */
curses_suite_init_failure_message_handler(const CU_pSuite pSuite)1339 static void curses_suite_init_failure_message_handler(const CU_pSuite pSuite)
1340 {
1341 assert(pSuite);
1342 f_uiTestsSkipped += pSuite->uiNumberOfTests;
1343 f_uiSuitesSkipped++;
1344
1345 refresh_summary_window();
1346 refresh_progress_window();
1347 }
1348
1349 /** @} */
1350