📄 curses.c
字号:
/*
* CUnit - A Unit testing framework library for C.
* Copyright (C) 2001 Anil Kumar
* Copyright (C) 2004,2005,2006 Anil Kumar, Jerry St.Clair
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Implementation of the Curses based Test Interface.
*
* 01/Nov/2001 Started Curses based interface for CUnit. (AK)
*
* 04/Nov/2001 Added Scrolling Capability to the Details Window. (AK)
*
* 24/Nov/2001 Added List and Show Failure Capability to the Details Window.
* Also added group initialization failure message handler. (AK)
*
* 09-Aug-2004 New interface, made all curses local functions static. (JDS)
*/
/** @file
* Curses test interface with interactive output (implementation).
*/
/** @addtogroup Curses
@{
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <string.h>
#include <curses.h>
#include "CUnit.h"
#include "TestDB.h"
#include "Util.h"
#include "TestRun.h"
#include "CUCurses.h"
/*
* Type Definitions
*/
#ifndef false
#define false (0) /**< Local boolean definition for false. */
#endif
#ifndef true
#define true (~false) /**< Local boolean definition for true. */
#endif
/** Curses interface status flag. */
typedef enum
{
CONTINUE = 1, /**< Continue processing commands in current menu. */
MOVE_UP, /**< Move up to the previous menu. */
STOP /**< Stop processing (user selected 'Quit'). */
} STATUS;
/** Menu type. */
typedef enum
{
MAIN_MENU = 1,
GROUP_MENU
} MENU_TYPE;
/** Pointers to curses interface windows. */
typedef struct
{
WINDOW* pMainWin; /**< Main window. */
WINDOW* pTitleWin; /**< Title window. */
WINDOW* pProgressWin; /**< Progress bar window. */
WINDOW* pSummaryWin; /**< Summary window. */
WINDOW* pRunSummaryWin; /**< Run Summary window. */
WINDOW* pDetailsWin; /**< Details window. */
WINDOW* pOptionsWin; /**< Options window. */
} APPWINDOWS;
/** Window elements. */
typedef struct
{
WINDOW* pPad; /**< Pointer to the pad. */
unsigned int uiRows; /**< Number of rows in pad. */
unsigned int uiColumns; /**< Number of columns in pad. */
unsigned int uiPadRow; /**< Current pad row. */
unsigned int uiPadCol; /**< Current pad column. */
unsigned int uiWinLeft; /**< Left position of containing window. */
unsigned int uiWinTop; /**< Top position of containing window. */
unsigned int uiWinRows; /**< Number of rows in containing window. */
unsigned int uiWinColumns; /**< Number of columns in containing window. */
} APPPAD;
/*
* Constants definitions
*/
/** Standard string length. */
#define STRING_LENGTH 128
/** String holding main menu run options. */
static const char* MAIN_OPTIONS = "(R)un (S)elect Suite (L)ist (F)ailures (Q)uit";
/** String holding suite menu run options. */
static const char* SUITE_OPTIONS = "(R)un (S)elect Test (L)ist (F)ailures (U)p (Q)uit";
/*
* Color Pairs Initialized for the Various Parameter Display
*/
static const int CLEAR_COLOR = 1; /**< Clear color.*/
static const int TITLE_COLOR = 2; /**< Title color.*/
static const int PROGRESS_BACKGROUND_COLOR = 3; /**< progress bar background color.*/
static const int PROGRESS_SUCCESS_COLOR = 4; /**< Progress bar success color.*/
static const int PROGRESS_FAILURE_COLOR = 5; /**< Progress bar failure color.*/
static const int MENU_COLOR = 6; /**< Menu color.*/
/*
* Global Definitions
*/
static const char* const f_szProgress = "Progress "; /**< Test for progress bar. */
static const char* f_szOptions = NULL; /**< String containing options. */
static CU_pTest f_pCurrentTest = NULL; /**< Pointer to the test currently being run. */
static CU_pSuite f_pCurrentSuite = NULL; /**< Pointer to the suite currently being run. */
static unsigned int f_uiTotalTests = 0; /**< Number of tests in registered suites. */
static unsigned int f_uiTestsRun = 0; /**< Number of tests actually run. */
static unsigned int f_uiTestsSkipped = 0; /**< Number of tests skipped during run. */
static unsigned int f_uiTestsFailed = 0; /**< Number of tests having failed assertions. */
static unsigned int f_uiTestsRunSuccessful = 0; /**< Number of tests run with no failed assertions. */
static unsigned int f_uiTotalSuites = 0; /**< Number of registered suites. */
static unsigned int f_uiSuitesSkipped = 0; /**< Number of suites skipped during run. */
static short f_nLeft; /**< Left window position. */
static short f_nTop; /**< Top window position. */
static short f_nWidth; /**< Width of window. */
static short f_nHeight; /**< Height of window. */
/** Pointers to curses interface windows. */
static APPWINDOWS application_windows = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
/** Details window definition. */
static APPPAD details_pad = {NULL, 0, 0, 0, 0, 0, 0, 0, 0};
/*
* Function Declarations
*/
static bool initialize_windows(void);
static void uninitialize_windows(void);
static void refresh_windows(void);
static void refresh_title_window(void);
static void refresh_progress_window(void);
static void refresh_summary_window(void);
static void refresh_run_summary_window(void);
static void refresh_details_window(void);
static void refresh_options_window(void);
static bool create_pad(APPPAD* pPad, WINDOW* pParent, unsigned int uiRows, unsigned int uiCols);
static void scroll_window(int nCommand, APPPAD* pPad, void (*parent_refresh)(void));
static bool test_initialize(void);
static void show_progress_bar(void);
static const char* get_hotkey(const char* szStr, int* pPos);
static void read_input_string(const char szPropmt[], char szValue[], int nBytes);
static STATUS curses_registry_level_run(CU_pTestRegistry pRegistry);
static STATUS curses_suite_level_run(CU_pSuite pSuite);
static CU_ErrorCode curses_run_all_tests(CU_pTestRegistry pRegistry);
static CU_ErrorCode curses_run_suite_tests(CU_pSuite pSuite);
static CU_ErrorCode curses_run_single_test(CU_pSuite pSuite, CU_pTest pTest);
static void curses_test_start_message_handler(const CU_pTest pTest, const CU_pSuite pSuite);
static void curses_test_complete_message_handler(const CU_pTest pTest, const CU_pSuite pSuite,
const CU_pFailureRecord pFailure);
static void curses_all_tests_complete_message_handler(const CU_pFailureRecord pFailure);
static void curses_suite_init_failure_message_handler(const CU_pSuite pSuite);
static void list_suites(CU_pTestRegistry pRegistry);
static void list_tests(CU_pSuite pSuite);
static void show_failures(void);
static void reset_run_parameters(void);
/*------------------------------------------------------------------------*/
/** Run registered CUnit tests using the curses interface. */
void CU_curses_run_tests(void)
{
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
f_szOptions = MAIN_OPTIONS;
if (!initialize_windows()) {
return;
}
if (!test_initialize()) {
goto test_initialize_fail;
}
curses_registry_level_run(CU_get_registry());
/* THIS WAS COMMENTED OUT IN THE 1.1-1 SOURCE
f_uiTotalTests = 3000;
{
int i;
int iSucc = 0;
for (i = 0; i < 3000; i++, iSucc++) {
if (i && !(i%2000))
iSucc--;
f_uiTestsRun = i + 1;
f_uiTestsRunSuccessful = iSucc + 1;
refresh_progress_window();
refresh_summary_window();
refresh_run_summary_window();
}
}
f_uiTestsRunSuccessful = f_uiTestsRun = 0;
refresh_windows();
{
int i;
int iSucc = -1;
for (i = 0; i < 3000; i++, iSucc++) {
if (i && !(i%2000))
iSucc++;
f_uiTestsRun = i + 1;
f_uiTestsRunSuccessful = iSucc + 1;
refresh_progress_window();
refresh_summary_window();
refresh_run_summary_window();
}
}
*/
test_initialize_fail:
uninitialize_windows();
}
/*------------------------------------------------------------------------*/
/** Initialize the curses interface windows. */
static bool initialize_windows(void)
{
bool bStatus = false;
if (NULL == (application_windows.pMainWin = initscr())) {
goto main_fail;
}
start_color();
f_nLeft = application_windows.pMainWin->_begx;
f_nTop = application_windows.pMainWin->_begy;
f_nWidth = application_windows.pMainWin->_maxx;
f_nHeight = application_windows.pMainWin->_maxy;
if (NULL == (application_windows.pTitleWin = newwin(3, f_nWidth, 0, 0))) {
goto title_fail;
}
if (NULL == (application_windows.pProgressWin = newwin(2, f_nWidth, 3, 0))) {
goto progress_fail;
}
if (NULL == (application_windows.pSummaryWin = newwin(1, f_nWidth, 5, 0))) {
goto summary_fail;
}
if (NULL == (application_windows.pRunSummaryWin = newwin(1, f_nWidth, 6, 0))) {
goto run_summary_fail;
}
if (NULL == (application_windows.pDetailsWin = newwin(f_nHeight - f_nTop - 7 , f_nWidth, 7, 0))) {
goto details_fail;
}
if (NULL == (application_windows.pOptionsWin = newwin(1, f_nWidth, f_nHeight - f_nTop, 0))) {
goto option_fail;
}
curs_set(0);
noecho();
cbreak();
keypad(application_windows.pMainWin, CU_TRUE);
init_pair(CLEAR_COLOR, COLOR_WHITE, COLOR_BLACK);
init_pair(TITLE_COLOR, COLOR_WHITE, COLOR_BLACK);
init_pair(PROGRESS_BACKGROUND_COLOR, COLOR_BLACK, COLOR_WHITE);
init_pair(PROGRESS_SUCCESS_COLOR, COLOR_WHITE, COLOR_GREEN);
init_pair(PROGRESS_FAILURE_COLOR, COLOR_WHITE, COLOR_RED);
init_pair(MENU_COLOR, COLOR_WHITE, COLOR_BLACK);
refresh_windows();
bStatus = true;
goto main_fail;
/*
* Error Handlers for all the stages.
*/
option_fail:
delwin(application_windows.pDetailsWin);
details_fail:
delwin(application_windows.pRunSummaryWin);
run_summary_fail:
delwin(application_windows.pSummaryWin);
summary_fail:
delwin(application_windows.pProgressWin);
progress_fail:
delwin(application_windows.pTitleWin);
title_fail:
endwin();
main_fail:
return bStatus;
}
/*------------------------------------------------------------------------*/
/** Clean up and delete curses interface windows. */
static void uninitialize_windows(void)
{
curs_set(1);
echo();
nocbreak();
keypad(application_windows.pMainWin, CU_FALSE);
if (details_pad.pPad) {
delwin(details_pad.pPad);
}
delwin(application_windows.pOptionsWin);
delwin(application_windows.pDetailsWin);
delwin(application_windows.pRunSummaryWin);
delwin(application_windows.pSummaryWin);
delwin(application_windows.pProgressWin);
delwin(application_windows.pTitleWin);
clear();
refresh();
endwin();
}
/*------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -