📄 automated.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 Automated Test Interface. * * Feb 2002 Initial implementation. (AK) * * 13/Feb/2002 Added initial automated interface functions to generate * HTML based Run report. (AK) * * 23/Jul/2002 Changed HTML to XML Format file generation for Automated Tests. (AK) * * 27/Jul/2003 Fixed a bug which hinders the listing of all failures. (AK) * * 17-Jul-2004 New interface, doxygen comments, eliminate compiler warnings, * automated_run_tests now assigns a generic file name if * none has been supplied. (JDS) * * 30-Apr-2005 Added notification of failed suite cleanup function. (JDS) *//** @file * Automated test interface with xml result output (implementation). *//** @addtogroup Automated @{*/#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <assert.h>#include <string.h>#include <limits.h>#include <time.h>#include "CUnit.h"#include "TestDB.h"#include "Util.h"#include "TestRun.h"#include "Automated.h"static CU_pSuite f_pRunningSuite = NULL; /**< The running test suite. */static char f_szDefaultFileRoot[] = "CUnitAutomated"; /**< Default filename root for automated output files. */static char f_szTestListFileName[FILENAME_MAX] = ""; /**< Current output file name for the test listing file. */static char f_szTestResultFileName[FILENAME_MAX] = ""; /**< Current output file name for the test results file. */static FILE* f_pTestResultFile = NULL; /**< FILE pointer the test results file. */static CU_BOOL f_bWriting_CUNIT_RUN_SUITE = CU_FALSE; /**< Flag for keeping track of when a closing xml tag is required. */static CU_ErrorCode automated_list_all_tests(CU_pTestRegistry pRegistry, const char* szFilename);static CU_ErrorCode initialize_result_file(const char* szFilename);static CU_ErrorCode uninitialize_result_file(void);static void automated_run_all_tests(CU_pTestRegistry pRegistry);static void automated_test_start_message_handler(const CU_pTest pTest, const CU_pSuite pSuite);static void automated_test_complete_message_handler(const CU_pTest pTest, const CU_pSuite pSuite, const CU_pFailureRecord pFailure);static void automated_all_tests_complete_message_handler(const CU_pFailureRecord pFailure);static void automated_suite_init_failure_message_handler(const CU_pSuite pSuite);static void automated_suite_cleanup_failure_message_handler(const CU_pSuite pSuite);/*------------------------------------------------------------------------*//** Run CUnit tests using the automated interface. * This function sets appropriate callback functions, * initializes the test output files, and calls the * appropriate functions to list the tests and run them. * If an output file name root has not been specified using * CU_set_output_filename(), a generic root will be applied. * It is an error to call this function before the CUnit * test registry has been initialized (check by assertion). */void CU_automated_run_tests(void){ assert(NULL != CU_get_registry()); /* Ensure output makes it to screen at the moment of a SIGSEGV. */ setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); /* if a filename root hasn't been set, use the default one */ if (0 == strlen(f_szTestResultFileName)) { CU_set_output_filename(f_szDefaultFileRoot); } if (CUE_SUCCESS != initialize_result_file(f_szTestResultFileName)) { fprintf(stderr, "\nERROR - Failed to create/initialize the result file."); } else { /* set up the message handlers for writing xml output */ CU_set_test_start_handler(automated_test_start_message_handler); CU_set_test_complete_handler(automated_test_complete_message_handler); CU_set_all_test_complete_handler(automated_all_tests_complete_message_handler); CU_set_suite_init_failure_handler(automated_suite_init_failure_message_handler); CU_set_suite_cleanup_failure_handler(automated_suite_cleanup_failure_message_handler); f_bWriting_CUNIT_RUN_SUITE = CU_FALSE; automated_run_all_tests(NULL); if (CUE_SUCCESS != uninitialize_result_file()) { fprintf(stderr, "\nERROR - Failed to close/uninitialize the result files."); } }}/*------------------------------------------------------------------------*//** Set the root file name for automated test output files. * The strings "-Listing.xml" and "-Results.xml" are appended to * the specified root to generate the filenames. If szFilenameRoot * is empty, the default root ("CUnitAutomated") is used. * @param szFilenameRoot String containing root to use for file names. */void CU_set_output_filename(const char* szFilenameRoot){ const char* szListEnding = "-Listing.xml"; const char* szResultEnding = "-Results.xml"; /* Construct the name for the listing file */ if (NULL != szFilenameRoot) { strncpy(f_szTestListFileName, szFilenameRoot, FILENAME_MAX - strlen(szListEnding) - 1); } else { strncpy(f_szTestListFileName, f_szDefaultFileRoot, FILENAME_MAX - strlen(szListEnding) - 1); } f_szTestListFileName[FILENAME_MAX - strlen(szListEnding) - 1] = '\0'; strcat(f_szTestListFileName, szListEnding); /* Construct the name for the result file */ if (NULL != szFilenameRoot) { strncpy(f_szTestResultFileName, szFilenameRoot, FILENAME_MAX - strlen(szResultEnding) - 1); } else { strncpy(f_szTestResultFileName, f_szDefaultFileRoot, FILENAME_MAX - strlen(szResultEnding) - 1); } f_szTestResultFileName[FILENAME_MAX - strlen(szResultEnding) - 1] = '\0'; strcat(f_szTestResultFileName, szResultEnding);}/*------------------------------------------------------------------------*//** Generate an xml file containing a list of all tests in all * suites in the active registry. * The output file will be named according to the most recent * call to CU_set_output_filename(), or a default if not * previously set. * @return An error code indicating the error status. */CU_ErrorCode CU_list_tests_to_file(){ /* if a filename root hasn't been set, use the default one */ if (0 == strlen(f_szTestListFileName)) { CU_set_output_filename(f_szDefaultFileRoot); } return automated_list_all_tests(CU_get_registry(), f_szTestListFileName);}/*------------------------------------------------------------------------*//** Run the registered tests using the automated interface. * If non-NULL. the specified registry is set as the active * registry for running the tests. If NULL, then the default * CUnit test registry is used. The actual test running is * performed by CU_run_all_tests(). * @param pRegistry The test registry to run. */static void automated_run_all_tests(CU_pTestRegistry pRegistry){ CU_pTestRegistry pOldRegistry = NULL; assert(NULL != f_pTestResultFile); f_pRunningSuite = NULL; if (NULL != pRegistry) { pOldRegistry = CU_set_registry(pRegistry); } fprintf(f_pTestResultFile," <CUNIT_RESULT_LISTING> \n"); CU_run_all_tests(); if (NULL != pRegistry) { CU_set_registry(pOldRegistry); }}/*------------------------------------------------------------------------*//** Initialize the test results file generated by the automated interface. * A file stream is opened and header information is written. */static CU_ErrorCode initialize_result_file(const char* szFilename){ CU_set_error(CUE_SUCCESS); if ((NULL == szFilename) || (strlen(szFilename) == 0)) { CU_set_error(CUE_BAD_FILENAME); } else if (NULL == (f_pTestResultFile = fopen(szFilename, "w"))) { CU_set_error(CUE_FOPEN_FAILED); } else { setvbuf(f_pTestResultFile, NULL, _IONBF, 0); fprintf(f_pTestResultFile, "<?xml version=\"1.0\" ?> \n" "<?xml-stylesheet type=\"text/xsl\" href=\"CUnit-Run.xsl\" ?> \n" "<!DOCTYPE CUNIT_TEST_RUN_REPORT SYSTEM \"CUnit-Run.dtd\"> \n" "<CUNIT_TEST_RUN_REPORT> \n" " <CUNIT_HEADER/> \n"); } return CU_get_error();}/*------------------------------------------------------------------------*//** Handler function called at start of each test. * The test result file must have been opened before this * function is called (i.e. f_pTestResultFile non-NULL). * @param pTest The test being run (non-NULL). * @param pSuite The suite containing the test (non-NULL). */static void automated_test_start_message_handler(const CU_pTest pTest, const CU_pSuite pSuite){ CU_UNREFERENCED_PARAMETER(pTest); /* not currently used */ assert(NULL != pTest); assert(NULL != pSuite); assert(NULL != f_pTestResultFile); /* write suite close/open tags if this is the 1st test for this szSuite */ if ((NULL == f_pRunningSuite) || (f_pRunningSuite != pSuite)) { if (CU_TRUE == f_bWriting_CUNIT_RUN_SUITE) { fprintf(f_pTestResultFile, " </CUNIT_RUN_SUITE_SUCCESS> \n" " </CUNIT_RUN_SUITE> \n"); } fprintf(f_pTestResultFile, " <CUNIT_RUN_SUITE> \n" " <CUNIT_RUN_SUITE_SUCCESS> \n" " <SUITE_NAME> %s </SUITE_NAME> \n", (NULL != pSuite->pName) ? pSuite->pName : ""); f_bWriting_CUNIT_RUN_SUITE = CU_TRUE; f_pRunningSuite = pSuite; }}/*------------------------------------------------------------------------*//** Handler function called at completion of each test. * @param pTest The test being run (non-NULL). * @param pSuite The suite containing the test (non-NULL). * @param pFailure Pointer to the 1st failure record for this test. */static void automated_test_complete_message_handler(const CU_pTest pTest, const CU_pSuite pSuite, const CU_pFailureRecord pFailure){ CU_pFailureRecord pTempFailure = pFailure; CU_UNREFERENCED_PARAMETER(pSuite); /* pSuite is not used except in assertion */ assert(NULL != pTest); assert(NULL != pSuite); assert(NULL != f_pTestResultFile); if (NULL != pTempFailure) { /* worst cast is a string of special chars */ char szTemp[CUNIT_MAX_ENTITY_LEN * CUNIT_MAX_STRING_LENGTH]; while (NULL != pTempFailure) { assert((NULL != pTempFailure->pSuite) && (pTempFailure->pSuite == pSuite)); assert((NULL != pTempFailure->pTest) && (pTempFailure->pTest == pTest));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -