⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 automated.c

📁 CUNIT c 测试框架,类似大名鼎鼎的junit,很有用的,这里是原代码,可以编译生成lib文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *  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 + -