diff --git a/pde-test-host/Makefile b/pde-test-host/Makefile new file mode 100644 index 0000000..cf1990a --- /dev/null +++ b/pde-test-host/Makefile @@ -0,0 +1,16 @@ +SHELL = /bin/bash +.ONESHELL: + .SHELLFLAGS += -e + + +MAIN_TARGET = $(PDE_TEST_HOST) +DERIVED_TARGETS = pde-test-host-dev_$(PDE_TEST_HOST_VERSION_FULL)_all.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + pushd pde-test-host + dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) + popd + + mv $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/pde-test-host/pde-test-host/Makefile b/pde-test-host/pde-test-host/Makefile new file mode 100644 index 0000000..ee6b671 --- /dev/null +++ b/pde-test-host/pde-test-host/Makefile @@ -0,0 +1,121 @@ +#********************************************************************* +# +# (C) Copyright Broadcom Corporation 2013-2014 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +#********************************************************************* + +export BCM_PHY_LIST := 82764 84752 84328 84740 8750 84328 542XX +BOARD_LIST=EMPTY + +export BCM_PTL_SPT=1 +export BCM_56850_A0=1 +export BCM_56860_A0=1 +export BCM_56960_A0=1 +export BCM_56970_A0=1 +export BCM_56970_B0=1 +export BCM_56980_A0=1 +export BCM_56980_B0=1 +export BCM_56870_A0=1 +export BCM_56340_A0=1 + +CFLAGS += -DBCM_ESW_SUPPORT +CFLAGS += -DINCLUDE_L3 + + +ifeq ($(SAI_ROOT),) + SAI_ROOT := $(shell echo $(dir $(abspath $(firstword $(MAKEFILE_LIST)))) | sed -e 's/\(.*\)\/.*output\/.*/\1/') +endif +export SAI_ROOT + +ifeq ($(OUTPATH),) + OUTPATH := $(dir $(abspath $(firstword $(MAKEFILE_LIST)))) +endif +export OUTPATH + + +ifeq ($(DEBIAN_PKG),) +INCLUDE_FLAGS += -I$(SAI_ROOT)include -I$(SAI_ROOT)/unittests -I$(SAI_ROOT)/include/pcap -I$(SAI_ROOT)/include/hiredis -I$(SAI_ROOT)../../../sonic-sairedis/SAI/inc +endif + + + +UNITTEST_OBJS := $(OUTPATH)unittest_objs +CUNIT_OBJS := $(OUTPATH)cunit_objs +PCAP_LIBS := $(SAI_ROOT)libpcap +HIREDIS_LIB := $(SAI_ROOT)libhiredis + +unittest_source_files = $(strip $(wildcard $(SAI_ROOT)/unittests/*.c)) +cunit_source_files = $(strip $(wildcard $(SAI_ROOT)/cunit/*.c)) + +test_source_files := $(wildcard $(SAI_ROOT)/test_adapter_host.c) +wb_src_files := $(wildcard $(SAI_ROOT)/wb_test.c) +ptf_setup_file := $(wildcard $(SAI_ROOT)/ptf_setup.c) +sai_includes := $(wildcard $(SAI_ROOT)/include/*.h) + + +test_host:=$(SAI_ROOT)/pde-test-host + +vpath %.h $(sai_includes) + +ifneq (,$(unittest_source_files)) +vpath %.c $(realpath $(SAI_ROOT)/unittests) +vpath %.o $(UNITTEST_OBJS)/ +endif + +ifneq (,$(cunit_source_files)) +vpath %.c $(realpath $(SAI_ROOT)/cunit) +vpath %.o $(CUNIT_OBJS)/ +endif + +all: $(test_host) + +unittest_objs := $(addprefix $(UNITTEST_OBJS)/, $(notdir $(unittest_source_files:.c=.o))) +cunit_objs := $(addprefix $(CUNIT_OBJS)/, $(notdir $(cunit_source_files:.c=.o))) + +cunit_archive = $(abspath $(CUNIT_OBJS)/cunit.a) +unittest_archive = $(abspath $(UNITTEST_OBJS)/unit_test.a) + +$(unittest_objs): $(UNITTEST_OBJS)/%.o : %.c + mkdir -p $(UNITTEST_OBJS) + $(CC) $(INCLUDE_FLAGS) $(CFLAGS_SAI_SDK) $(CFLAGS) -c $^ -o $@ + +$(cunit_objs): $(CUNIT_OBJS)/%.o : %.c + mkdir -p $(CUNIT_OBJS) + $(CC) $(INCLUDE_FLAGS) $(CFLAGS_SAI_SDK) $(CFLAGS) -c $^ -o $@ + +$(unittest_archive): $(unittest_objs) + $(RM) -f $@ + $(AR) cq $@ $^ + +$(cunit_archive): $(cunit_objs) + $(RM) -f $@ + $(AR) cq $@ $^ + +$(test_host): $(test_source_files:.o=.c) $(unittest_archive) $(cunit_archive) + + $(CC) -g -O0 $(INCLUDE_FLAGS) $(CLAGS_SAI_SDK) $^ -lpthread -l:libpcap.so -l:libsai.so.1 -ldl -rdynamic -o $@ + +clean: + @echo "Cleaning test only files." + $(RM) -f $(test_host) + $(RM) -f $(UNITTEST_OBJS)/* + $(RM) -f $(CUNIT_OBJS)/* + +cleantestall: + @echo "Cleaning test files including dirs." + $(RM) -f $(test_host) + $(RM) -rf $(UNITTEST_OBJS) + $(RM) -rf $(CUNIT_OBJS) diff --git a/pde-test-host/pde-test-host/cunit/Automated.c b/pde-test-host/pde-test-host/cunit/Automated.c new file mode 100755 index 0000000..79d5a68 --- /dev/null +++ b/pde-test-host/pde-test-host/cunit/Automated.c @@ -0,0 +1,623 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2001 Anil Kumar + * Copyright (C) 2004-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) + * + * 02-May-2006 Added internationalization hooks. (JDS) + */ + +/** @file + * Automated test interface with xml result output (implementation). + */ +/** @addtogroup Automated + @{ +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "CUnit.h" +#include "TestDB.h" +#include "MyMem.h" +#include "Util.h" +#include "TestRun.h" +#include "Automated.h" +#include "CUnit_intl.h" + +#define MAX_FILENAME_LENGTH 1025 + +/*================================================================= + * Global / Static data definitions + *=================================================================*/ +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[MAX_FILENAME_LENGTH] = ""; /**< Current output file name for the test listing file. */ +static char f_szTestResultFileName[MAX_FILENAME_LENGTH] = ""; /**< 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 function forward declarations + *=================================================================*/ +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); + +/*================================================================= + * Public Interface functions + *=================================================================*/ +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, "\n%s", _("ERROR - 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, "\n%s", _("ERROR - Failed to close/uninitialize the result files.")); + } + } +} + +/*------------------------------------------------------------------------*/ +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, MAX_FILENAME_LENGTH - strlen(szListEnding) - 1); + } + else { + strncpy(f_szTestListFileName, f_szDefaultFileRoot, MAX_FILENAME_LENGTH - strlen(szListEnding) - 1); + } + + f_szTestListFileName[MAX_FILENAME_LENGTH - strlen(szListEnding) - 1] = '\0'; + strcat(f_szTestListFileName, szListEnding); + + /* Construct the name for the result file */ + if (NULL != szFilenameRoot) { + strncpy(f_szTestResultFileName, szFilenameRoot, MAX_FILENAME_LENGTH - strlen(szResultEnding) - 1); + } + else { + strncpy(f_szTestResultFileName, f_szDefaultFileRoot, MAX_FILENAME_LENGTH - strlen(szResultEnding) - 1); + } + + f_szTestResultFileName[MAX_FILENAME_LENGTH - strlen(szResultEnding) - 1] = '\0'; + strcat(f_szTestResultFileName, szResultEnding); +} + +/*------------------------------------------------------------------------*/ +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); +} + +/*================================================================= + * Static function implementation + *=================================================================*/ +/** Runs 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," \n"); + CU_run_all_tests(); + if (NULL != pRegistry) { + CU_set_registry(pOldRegistry); + } +} + +/*------------------------------------------------------------------------*/ +/** Initializes 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) +{ + char* szTime; + time_t tTime = 0; + + 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); + + time(&tTime); + szTime = ctime(&tTime); + fprintf(f_pTestResultFile, + " \n" + " \n" + " Test run start - %s \n", + (NULL != szTime) ? szTime : ""); + } + + 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 != pSuite->pName); + 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, + " \n" + " \n"); + } + + fprintf(f_pTestResultFile, + " \n" + " \n" + " %s \n", + 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) +{ + char *szTemp = NULL; + size_t szTemp_len = 0; + size_t cur_len = 0; + CU_pFailureRecord pTempFailure = pFailure; + + CU_UNREFERENCED_PARAMETER(pSuite); /* pSuite is not used except in assertion */ + + assert(NULL != pTest); + assert(NULL != pTest->pName); + assert(NULL != pSuite); + assert(NULL != pSuite->pName); + assert(NULL != f_pTestResultFile); + + if (NULL != pTempFailure) { + + while (NULL != pTempFailure) { + + assert((NULL != pTempFailure->pSuite) && (pTempFailure->pSuite == pSuite)); + assert((NULL != pTempFailure->pTest) && (pTempFailure->pTest == pTest)); + + /* expand temporary char buffer if need more room */ + if (NULL != pTempFailure->strCondition) { + cur_len = CU_translated_strlen(pTempFailure->strCondition) + 1; + } + else { + cur_len = 1; + } + if (cur_len > szTemp_len) { + szTemp_len = cur_len; + if (NULL != szTemp) { + CU_FREE(szTemp); + } + szTemp = (char *)CU_MALLOC(szTemp_len); + } + + /* convert xml entities in strCondition (if present) */ + if (NULL != pTempFailure->strCondition) { + CU_translate_special_characters(pTempFailure->strCondition, szTemp, szTemp_len); + } + else { + szTemp[0] = '\0'; + } + + fprintf(f_pTestResultFile, + " \n" + " \n" + " %s \n" + " %s \n" + " %u \n" + " %s \n" + " \n" + " \n", + pTest->pName, + (NULL != pTempFailure->strFileName) ? pTempFailure->strFileName : "", + pTempFailure->uiLineNumber, + szTemp); + pTempFailure = pTempFailure->pNext; + } + } + else { + fprintf(f_pTestResultFile, + " \n" + " \n" + " %s \n" + " \n" + " \n", + pTest->pName); + } + + if (NULL != szTemp) { + CU_FREE(szTemp); + } +} + +/*------------------------------------------------------------------------*/ +/** Handler function called at completion of all tests in a suite. + * @param pFailure Pointer to the test failure record list. + */ +static void automated_all_tests_complete_message_handler(const CU_pFailureRecord pFailure) +{ + CU_pTestRegistry pRegistry = CU_get_registry(); + CU_pRunSummary pRunSummary = CU_get_run_summary(); + + CU_UNREFERENCED_PARAMETER(pFailure); /* not used */ + + assert(NULL != pRegistry); + assert(NULL != pRunSummary); + assert(NULL != f_pTestResultFile); + + if ((NULL != f_pRunningSuite) && (CU_TRUE == f_bWriting_CUNIT_RUN_SUITE)) { + fprintf(f_pTestResultFile, + " \n" + " \n"); + } + + fprintf(f_pTestResultFile, + " \n" + " \n"); + + fprintf(f_pTestResultFile, + " \n" + " %s \n" + " %u \n" + " %u \n" + " - NA - \n" + " %u \n" + " %u \n" + " \n", + _("Suites"), + pRegistry->uiNumberOfSuites, + pRunSummary->nSuitesRun, + pRunSummary->nSuitesFailed, + pRunSummary->nSuitesInactive + ); + + fprintf(f_pTestResultFile, + " \n" + " %s \n" + " %u \n" + " %u \n" + " %u \n" + " %u \n" + " %u \n" + " \n", + _("Test Cases"), + pRegistry->uiNumberOfTests, + pRunSummary->nTestsRun, + pRunSummary->nTestsRun - pRunSummary->nTestsFailed, + pRunSummary->nTestsFailed, + pRunSummary->nTestsInactive + ); + + fprintf(f_pTestResultFile, + " \n" + " %s \n" + " %u \n" + " %u \n" + " %u \n" + " %u \n" + " %s \n" + " \n" + " \n", + _("Assertions"), + pRunSummary->nAsserts, + pRunSummary->nAsserts, + pRunSummary->nAsserts - pRunSummary->nAssertsFailed, + pRunSummary->nAssertsFailed, + _("n/a") + ); +} + +/*------------------------------------------------------------------------*/ +/** Handler function called when suite initialization fails. + * @param pSuite The suite for which initialization failed. + */ +static void automated_suite_init_failure_message_handler(const CU_pSuite pSuite) +{ + assert(NULL != pSuite); + assert(NULL != pSuite->pName); + assert(NULL != f_pTestResultFile); + + if (CU_TRUE == f_bWriting_CUNIT_RUN_SUITE) { + fprintf(f_pTestResultFile, + " \n" + " \n"); + f_bWriting_CUNIT_RUN_SUITE = CU_FALSE; + } + + fprintf(f_pTestResultFile, + " \n" + " \n" + " %s \n" + " %s \n" + " \n" + " \n", + pSuite->pName, + _("Suite Initialization Failed")); +} + +/*------------------------------------------------------------------------*/ +/** Handler function called when suite cleanup fails. + * @param pSuite The suite for which cleanup failed. + */ +static void automated_suite_cleanup_failure_message_handler(const CU_pSuite pSuite) +{ + assert(NULL != pSuite); + assert(NULL != pSuite->pName); + assert(NULL != f_pTestResultFile); + + if (CU_TRUE == f_bWriting_CUNIT_RUN_SUITE) { + fprintf(f_pTestResultFile, + " \n" + " \n"); + f_bWriting_CUNIT_RUN_SUITE = CU_FALSE; + } + + fprintf(f_pTestResultFile, + " \n" + " \n" + " %s \n" + " %s \n" + " \n" + " \n", + pSuite->pName, + _("Suite Cleanup Failed")); +} + +/*------------------------------------------------------------------------*/ +/** Finalizes and closes the results output file generated + * by the automated interface. + */ +static CU_ErrorCode uninitialize_result_file(void) +{ + + assert(NULL != f_pTestResultFile); + + CU_set_error(CUE_SUCCESS); + + fprintf(f_pTestResultFile,""); + + if (0 != fflush(f_pTestResultFile)) { + CU_set_error(CUE_FCLOSE_FAILED); + } + + if (0 != fclose(f_pTestResultFile)) { + CU_set_error(CUE_FCLOSE_FAILED); + } + + return CU_get_error(); +} + +/*------------------------------------------------------------------------*/ +/** Generates an xml listing of all tests in all suites for the + * specified test registry. The output is directed to a file + * having the specified name. + * @param pRegistry Test registry for which to generate list (non-NULL). + * @param szFilename Non-NULL, non-empty string containing name for + * listing file. + * @return A CU_ErrorCode indicating the error status. + */ +static CU_ErrorCode automated_list_all_tests(CU_pTestRegistry pRegistry, const char* szFilename) +{ + CU_pSuite pSuite = NULL; + CU_pTest pTest = NULL; + FILE* pTestListFile = NULL; + char* szTime; + time_t tTime = 0; + + CU_set_error(CUE_SUCCESS); + + if (NULL == pRegistry) { + CU_set_error(CUE_NOREGISTRY); + } + else if ((NULL == szFilename) || (0 == strlen(szFilename))) { + CU_set_error(CUE_BAD_FILENAME); + } + else if (NULL == (pTestListFile = fopen(f_szTestListFileName, "w"))) { + CU_set_error(CUE_FOPEN_FAILED); + } + else { + setvbuf(pTestListFile, NULL, _IONBF, 0); + + fprintf(pTestListFile, + " \n" + " \n" + " \n" + " \n"); + + fprintf(pTestListFile, + " \n" + " %s \n" + " %u \n" + " \n", + _("Total Number of Suites"), + pRegistry->uiNumberOfSuites); + + fprintf(pTestListFile, + " \n" + " %s \n" + " %u \n" + " \n" + " \n", + _("Total Number of Test Cases"), + pRegistry->uiNumberOfTests); + + fprintf(pTestListFile, + " \n"); + + pSuite = pRegistry->pSuite; + while (NULL != pSuite) { + assert(NULL != pSuite->pName); + pTest = pSuite->pTest; + + fprintf(pTestListFile, + " \n" + " \n" + " %s \n" + " %s \n" + " %s \n" + " %s \n" + " %u \n" + " \n", + pSuite->pName, + (NULL != pSuite->pInitializeFunc) ? _("Yes") : _("No"), + (NULL != pSuite->pCleanupFunc) ? _("Yes") : _("No"), + (CU_FALSE != pSuite->fActive) ? _("Yes") : _("No"), + pSuite->uiNumberOfTests); + + fprintf(pTestListFile, + " \n"); + while (NULL != pTest) { + assert(NULL != pTest->pName); + fprintf(pTestListFile, + " \n" + " %s \n" + " %s \n" + " \n", + pTest->pName, + (CU_FALSE != pSuite->fActive) ? _("Yes") : _("No")); + pTest = pTest->pNext; + } + + fprintf(pTestListFile, + " \n" + " \n"); + + pSuite = pSuite->pNext; + } + + fprintf(pTestListFile, " \n"); + + time(&tTime); + szTime = ctime(&tTime); + fprintf(pTestListFile, + " %s" CU_VERSION " - %s \n" + "", + _("File Generated By CUnit v"), + (NULL != szTime) ? szTime : ""); + + if (0 != fclose(pTestListFile)) { + CU_set_error(CUE_FCLOSE_FAILED); + } + } + + return CU_get_error(); +} + +/** @} */ diff --git a/pde-test-host/pde-test-host/cunit/Basic.c b/pde-test-host/pde-test-host/cunit/Basic.c new file mode 100755 index 0000000..181f3b9 --- /dev/null +++ b/pde-test-host/pde-test-host/cunit/Basic.c @@ -0,0 +1,334 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2004-2006 Jerry St.Clair, Anil Kumar + * + * 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 for basic test runner interface. + * + * 11-Aug-2004 Initial implementation of basic test runner interface. (JDS) + * + * 8-Jan-2005 Fixed reporting bug (bug report cunit-Bugs-1093861). (JDS) + * + * 30-Apr-2005 Added notification of suite cleanup failure. (JDS) + * + * 02-May-2006 Added internationalization hooks. (JDS) + */ + +/** @file + * Basic interface with output to stdout. + */ +/** @addtogroup Basic + * @{ + */ + +#include +#include +#include +#include +#include + +#include "CUnit.h" +#include "TestDB.h" +#include "Util.h" +#include "TestRun.h" +#include "Basic.h" +#include "CUnit_intl.h" + +/*================================================================= + * Global/Static Definitions + *=================================================================*/ +/** Pointer to the currently running suite. */ +CU_pSuite f_pRunningSuite = NULL; +/** Current run mode. */ +static CU_BasicRunMode f_run_mode = CU_BRM_NORMAL; + +/*================================================================= + * Forward declaration of module functions * + *=================================================================*/ +CU_ErrorCode basic_initialize(void); +static CU_ErrorCode basic_run_all_tests(CU_pTestRegistry pRegistry); +static CU_ErrorCode basic_run_suite(CU_pSuite pSuite); +static CU_ErrorCode basic_run_single_test(CU_pSuite pSuite, CU_pTest pTest); + +static void basic_test_start_message_handler(const CU_pTest pTest, const CU_pSuite pSuite); +static void basic_test_complete_message_handler(const CU_pTest pTest, const CU_pSuite pSuite, const CU_pFailureRecord pFailureList); +static void basic_all_tests_complete_message_handler(const CU_pFailureRecord pFailure); +static void basic_suite_init_failure_message_handler(const CU_pSuite pSuite); +static void basic_suite_cleanup_failure_message_handler(const CU_pSuite pSuite); + +/*================================================================= + * Public Interface functions + *=================================================================*/ +CU_ErrorCode CU_basic_run_tests(void) +{ + CU_ErrorCode error; + + if (NULL == CU_get_registry()) { + if (CU_BRM_SILENT != f_run_mode) + fprintf(stderr, "\n\n%s\n", _("FATAL ERROR - Test registry is not initialized.")); + error = CUE_NOREGISTRY; + } + else if (CUE_SUCCESS == (error = basic_initialize())) + error = basic_run_all_tests(NULL); + + return error; +} + +/*------------------------------------------------------------------------*/ +CU_ErrorCode CU_basic_run_suite(CU_pSuite pSuite) +{ + CU_ErrorCode error; + + if (NULL == pSuite) + error = CUE_NOSUITE; + else if (CUE_SUCCESS == (error = basic_initialize())) + error = basic_run_suite(pSuite); + + return error; +} + +/*------------------------------------------------------------------------*/ +CU_ErrorCode CU_basic_run_test(CU_pSuite pSuite, CU_pTest pTest) +{ + CU_ErrorCode error; + + if (NULL == pSuite) + error = CUE_NOSUITE; + else if (NULL == pTest) + error = CUE_NOTEST; + else if (CUE_SUCCESS == (error = basic_initialize())) + error = basic_run_single_test(pSuite, pTest); + + return error; +} + +/*------------------------------------------------------------------------*/ +void CU_basic_set_mode(CU_BasicRunMode mode) +{ + f_run_mode = mode; +} + +/*------------------------------------------------------------------------*/ +CU_BasicRunMode CU_basic_get_mode(void) +{ + return f_run_mode; +} + +/*------------------------------------------------------------------------*/ +void CU_basic_show_failures(CU_pFailureRecord pFailure) +{ + int i; + + for (i = 1 ; (NULL != pFailure) ; pFailure = pFailure->pNext, i++) { + fprintf(stdout, "\n %d. %s:%u - %s", i, + (NULL != pFailure->strFileName) ? pFailure->strFileName : "", + pFailure->uiLineNumber, + (NULL != pFailure->strCondition) ? pFailure->strCondition : ""); + } +} + +/*================================================================= + * Static module functions + *=================================================================*/ +/** Performs inialization actions for the basic interface. + * This includes setting output to unbuffered, printing a + * welcome message, and setting the test run handlers. + * @return An error code indicating the framework error condition. + */ +CU_ErrorCode basic_initialize(void) +{ + /* Unbuffered output so everything reaches the screen */ + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); + + CU_set_error(CUE_SUCCESS); + + if (CU_BRM_SILENT != f_run_mode) + fprintf(stdout, "\n\n %s" CU_VERSION + "\n %s\n\n", + _("CUnit - A unit testing framework for C - Version "), + _("http://cunit.sourceforge.net/")); + + CU_set_test_start_handler(basic_test_start_message_handler); + CU_set_test_complete_handler(basic_test_complete_message_handler); + CU_set_all_test_complete_handler(basic_all_tests_complete_message_handler); + CU_set_suite_init_failure_handler(basic_suite_init_failure_message_handler); + CU_set_suite_cleanup_failure_handler(basic_suite_cleanup_failure_message_handler); + + return CU_get_error(); +} + +/*------------------------------------------------------------------------*/ +/** Runs all tests within the basic interface. + * If non-NULL, the test registry is changed to the specified registry + * before running the tests, and reset to the original registry when + * done. If NULL, the default CUnit test registry will be used. + * @param pRegistry The CU_pTestRegistry containing the tests + * to be run. If NULL, use the default registry. + * @return An error code indicating the error status + * during the test run. + */ +static CU_ErrorCode basic_run_all_tests(CU_pTestRegistry pRegistry) +{ + CU_pTestRegistry pOldRegistry = NULL; + CU_ErrorCode result; + + f_pRunningSuite = NULL; + + if (NULL != pRegistry) + pOldRegistry = CU_set_registry(pRegistry); + result = CU_run_all_tests(); + if (NULL != pRegistry) + CU_set_registry(pOldRegistry); + return result; +} + +/*------------------------------------------------------------------------*/ +/** Runs a specified suite within the basic interface. + * @param pSuite The suite to be run (non-NULL). + * @return An error code indicating the error status + * during the test run. + */ +static CU_ErrorCode basic_run_suite(CU_pSuite pSuite) +{ + f_pRunningSuite = NULL; + return CU_run_suite(pSuite); +} + +/*------------------------------------------------------------------------*/ +/** Runs a single test for the specified suite within + * the console interface. + * @param pSuite The suite containing the test to be run (non-NULL). + * @param pTest The test to be run (non-NULL). + * @return An error code indicating the error status + * during the test run. + */ +static CU_ErrorCode basic_run_single_test(CU_pSuite pSuite, CU_pTest pTest) +{ + f_pRunningSuite = NULL; + return CU_run_test(pSuite, pTest); +} + +/*------------------------------------------------------------------------*/ +/** Handler function called at start of each test. + * @param pTest The test being run. + * @param pSuite The suite containing the test. + */ +static void basic_test_start_message_handler(const CU_pTest pTest, const CU_pSuite pSuite) +{ + assert(NULL != pSuite); + assert(NULL != pTest); + + if (CU_BRM_VERBOSE == f_run_mode) { + assert(NULL != pTest->pName); + if ((NULL == f_pRunningSuite) || (f_pRunningSuite != pSuite)) { + assert(NULL != pSuite->pName); + fprintf(stdout, "\n%s: %s", _("Suite"), pSuite->pName); + fprintf(stdout, "\n %s: %s ...", _("Test"), pTest->pName); + f_pRunningSuite = pSuite; + } + else { + fprintf(stdout, "\n %s: %s ...", _("Test"), pTest->pName); + } + } +} + +/*------------------------------------------------------------------------*/ +/** Handler function called at completion of each test. + * @param pTest The test being run. + * @param pSuite The suite containing the test. + * @param pFailure Pointer to the 1st failure record for this test. + */ +static void basic_test_complete_message_handler(const CU_pTest pTest, + const CU_pSuite pSuite, + const CU_pFailureRecord pFailureList) +{ + CU_pFailureRecord pFailure = pFailureList; + int i; + + assert(NULL != pSuite); + assert(NULL != pTest); + + if (NULL == pFailure) { + if (CU_BRM_VERBOSE == f_run_mode) { + fprintf(stdout, _("passed")); + } + } + else { + switch (f_run_mode) { + case CU_BRM_VERBOSE: + fprintf(stdout, _("FAILED")); + break; + case CU_BRM_NORMAL: + assert(NULL != pSuite->pName); + assert(NULL != pTest->pName); + fprintf(stdout, _("\nSuite %s, Test %s had failures:"), pSuite->pName, pTest->pName); + break; + default: /* gcc wants all enums covered. ok. */ + break; + } + if (CU_BRM_SILENT != f_run_mode) { + for (i = 1 ; (NULL != pFailure) ; pFailure = pFailure->pNext, i++) { + fprintf(stdout, "\n %d. %s:%u - %s", i, + (NULL != pFailure->strFileName) ? pFailure->strFileName : "", + pFailure->uiLineNumber, + (NULL != pFailure->strCondition) ? pFailure->strCondition : ""); + } + } + } +} + +/*------------------------------------------------------------------------*/ +/** Handler function called at completion of all tests in a suite. + * @param pFailure Pointer to the test failure record list. + */ +static void basic_all_tests_complete_message_handler(const CU_pFailureRecord pFailure) +{ + CU_UNREFERENCED_PARAMETER(pFailure); /* not used in basic interface */ + printf("\n\n"); + CU_print_run_results(stdout); + printf("\n"); +} + +/*------------------------------------------------------------------------*/ +/** Handler function called when suite initialization fails. + * @param pSuite The suite for which initialization failed. + */ +static void basic_suite_init_failure_message_handler(const CU_pSuite pSuite) +{ + assert(NULL != pSuite); + assert(NULL != pSuite->pName); + + if (CU_BRM_SILENT != f_run_mode) + fprintf(stdout, _("\nWARNING - Suite initialization failed for '%s'."), pSuite->pName); +} + +/*------------------------------------------------------------------------*/ +/** Handler function called when suite cleanup fails. + * @param pSuite The suite for which cleanup failed. + */ +static void basic_suite_cleanup_failure_message_handler(const CU_pSuite pSuite) +{ + assert(NULL != pSuite); + assert(NULL != pSuite->pName); + + if (CU_BRM_SILENT != f_run_mode) + fprintf(stdout, _("\nWARNING - Suite cleanup failed for '%s'."), pSuite->pName); +} + +/** @} */ diff --git a/pde-test-host/pde-test-host/cunit/CUError.c b/pde-test-host/pde-test-host/cunit/CUError.c new file mode 100755 index 0000000..41f9bc3 --- /dev/null +++ b/pde-test-host/pde-test-host/cunit/CUError.c @@ -0,0 +1,231 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2001 Anil Kumar + * Copyright (C) 2004-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 + */ + +/* + * Error handling code used by CUnit + * + * 16-Jul-2004 Created access functions for error code, error action + * functions, messages for new error codes. (JDS) + * + * 02-May-2006 Added internationalization hooks. (JDS) + */ + +/** @file + * Error handling functions (implementation). + */ +/** @addtogroup Framework + @{ +*/ + +#include +#include + +#include "CUnit_intl.h" +#include "CUError.h" + +/*================================================================= + * Global/Static Definitions + *=================================================================*/ +/** Local variable holding the current error code. */ +static CU_ErrorCode g_error_number = CUE_SUCCESS; +/** Local variable holding the current error action code. */ +static CU_ErrorAction g_error_action = CUEA_IGNORE; + +/*================================================================= + * Private function forward declarations + *=================================================================*/ +static const char* get_error_desc(CU_ErrorCode error); + +#ifdef CUNIT_DO_NOT_DEFINE_UNLESS_BUILDING_TESTS +void test_exit(int status); +#endif + +/*================================================================= + * Public API functions + *=================================================================*/ +void CU_set_error(CU_ErrorCode error) +{ + if ((error != CUE_SUCCESS) && (g_error_action == CUEA_ABORT)) { +#ifndef CUNIT_DO_NOT_DEFINE_UNLESS_BUILDING_TESTS + fprintf(stderr, _("\nAborting due to error #%d: %s\n"), + (int)error, + get_error_desc(error)); + exit((int)error); +#else + test_exit(error); +#endif + } + + g_error_number = error; +} + +/*------------------------------------------------------------------------*/ +CU_ErrorCode CU_get_error(void) +{ + return g_error_number; +} + +/*------------------------------------------------------------------------*/ +const char* CU_get_error_msg(void) +{ + return get_error_desc(g_error_number); +} + +/*------------------------------------------------------------------------*/ +void CU_set_error_action(CU_ErrorAction action) +{ + g_error_action = action; +} + +/*------------------------------------------------------------------------*/ +CU_ErrorAction CU_get_error_action(void) +{ + return g_error_action; +} + +/*================================================================= + * Private static function definitions + *=================================================================*/ +/** Internal function to look up the error message for a specified + * error code. An empty string is returned if iError is not a member + * of CU_ErrorCode. If you add an error code to enum CU_ErrorCode, + * be sure to add a corresponding error message here. + * + * @param iError CU_ErrorCode to look up. + * @return Pointer to a string containing the error message. + * @see CU_get_error_msg() + */ +static const char* get_error_desc(CU_ErrorCode iError) +{ + int iMaxIndex; + + static const char* ErrorDescription[] = { + N_("No Error."), /* CUE_SUCCESS - 0 */ + N_("Memory allocation failed."), /* CUE_NOMEMORY - 1 */ + "", + "", + "", + "", + "", + "", + "", + "", + N_("Test registry does not exist."), /* CUE_NOREGISTRY - 10 */ + N_("Registry already exists."), /* CUE_REGISTRY_EXISTS - 11 */ + "", + "", + "", + "", + "", + "", + "", + "", + N_("NULL suite not allowed."), /* CUE_NOSUITE - 20 */ + N_("Suite name cannot be NULL."), /* CUE_NO_SUITENAME - 21 */ + N_("Suite initialization function failed."), /* CUE_SINIT_FAILED - 22 */ + N_("Suite cleanup function failed."), /* CUE_SCLEAN_FAILED - 23 */ + N_("Suite having name already registered."), /* CUE_DUP_SUITE - 24 */ + N_("Requested suite is not active."), /* CUE_SUITE_INACTIVE - 25 */ + "", + "", + "", + "", + N_("NULL test or test function not allowed."),/* CUE_NOTEST - 30 */ + N_("Test name cannot be NULL."), /* CUE_NO_TESTNAME - 31 */ + N_("Test having this name already in suite."),/* CUE_DUP_TEST - 32 */ + N_("Test not registered in specified suite."),/* CUE_TEST_NOT_IN_SUITE - 33 */ + N_("Requested test is not active"), /* CUE_TEST_INACTIVE - 34 */ + "", + "", + "", + "", + "", + N_("Error opening file."), /* CUE_FOPEN_FAILED - 40 */ + N_("Error closing file."), /* CUE_FCLOSE_FAILED - 41 */ + N_("Bad file name."), /* CUE_BAD_FILENAME - 42 */ + N_("Error during write to file."), /* CUE_WRITE_ERROR - 43 */ + N_("Undefined Error") + }; + + iMaxIndex = (int)(sizeof(ErrorDescription)/sizeof(char *) - 1); + if ((int)iError < 0) { + return _(ErrorDescription[0]); + } + else if ((int)iError > iMaxIndex) { + return _(ErrorDescription[iMaxIndex]); + } + else { + return _(ErrorDescription[(int)iError]); + } +} + +/** @} */ + +#ifdef CUNIT_BUILD_TESTS +#include "test_cunit.h" + +void test_cunit_CUError(void) +{ + CU_ErrorCode old_err = CU_get_error(); + CU_ErrorAction old_action = CU_get_error_action(); + + test_cunit_start_tests("CUError.c"); + + /* CU_set_error() & CU_get_error() */ + CU_set_error(CUE_NOMEMORY); + TEST(CU_get_error() != CUE_SUCCESS); + TEST(CU_get_error() == CUE_NOMEMORY); + + CU_set_error(CUE_NOREGISTRY); + TEST(CU_get_error() != CUE_SUCCESS); + TEST(CU_get_error() == CUE_NOREGISTRY); + + /* CU_get_error_msg() */ + CU_set_error(CUE_SUCCESS); + TEST(!strcmp(CU_get_error_msg(), get_error_desc(CUE_SUCCESS))); + + CU_set_error(CUE_NOTEST); + TEST(!strcmp(CU_get_error_msg(), get_error_desc(CUE_NOTEST))); + + CU_set_error(CUE_NOMEMORY); + TEST(!strcmp(CU_get_error_msg(), get_error_desc(CUE_NOMEMORY))); + TEST(strcmp(CU_get_error_msg(), get_error_desc(CUE_SCLEAN_FAILED))); + + TEST(!strcmp(get_error_desc(100), "Undefined Error")); + + /* CU_set_error_action() & CU_get_error_action() */ + CU_set_error_action(CUEA_FAIL); + TEST(CU_get_error_action() != CUEA_IGNORE); + TEST(CU_get_error_action() == CUEA_FAIL); + TEST(CU_get_error_action() != CUEA_ABORT); + + CU_set_error_action(CUEA_ABORT); + TEST(CU_get_error_action() != CUEA_IGNORE); + TEST(CU_get_error_action() != CUEA_FAIL); + TEST(CU_get_error_action() == CUEA_ABORT); + + /* reset values */ + CU_set_error(old_err); + CU_set_error_action(old_action); + + test_cunit_end_tests(); +} + +#endif /* CUNIT_BUILD_TESTS */ diff --git a/pde-test-host/pde-test-host/cunit/Console.c b/pde-test-host/pde-test-host/cunit/Console.c new file mode 100755 index 0000000..512e3e6 --- /dev/null +++ b/pde-test-host/pde-test-host/cunit/Console.c @@ -0,0 +1,735 @@ + /* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2001 Anil Kumar + * Copyright (C) 2004-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 Console Test Interface. + * + * Aug 2001 Initial implementation (AK) + * + * 19/Aug/2001 Added initial console interface functions without + * any run functionality. (AK) + * + * 24/Aug/2001 Added compare_strings, show_errors, list_suites, + * list_tests function declarations. (AK) + * + * 17-Jul-2004 New interface, doxygen comments, reformat console output. (JDS) + * + * 30-Apr-2005 Added notification of suite cleanup failure. (JDS) + * + * 24-Apr-2006 Suite/test selection is now by number rather than name. + * Inactive suites/tests now reported. + * Interface supports (de)activation of tests/suites. + * Help function added for both menu levels. + * Option menu added. Immediate action on hotkeys + * without needing to , like curses. (JDS) + * + * 02-May-2006 Added internationalization hooks. (JDS) + */ + +/** @file + * Console test interface with interactive output (implementation). + */ +/** @addtogroup Console + @{ +*/ + +#include +#include +#include +#include +#include + +#include "CUnit.h" +#include "TestDB.h" +#include "Util.h" +#include "TestRun.h" +#include "Console.h" +#include "CUnit_intl.h" + +extern int sai_driver_shell(); +extern int warmboot_enable, collect_syslog; + +/** Console interface status flag. */ +typedef enum +{ + CU_STATUS_CONTINUE = 1, /**< Continue processing commands in current menu. */ + CU_STATUS_MOVE_UP, /**< Move up to the previous menu. */ + CU_STATUS_STOP /**< Stop processing (user selected 'Quit'). */ +} CU_STATUS; + +/*================================================================= + * Global / Static data definitions + *=================================================================*/ +/** Pointer to the currently running suite. */ +static CU_pSuite f_pRunningSuite = NULL; + +/** Common width measurements for output formatting. */ +static size_t f_yes_width = 0; +static size_t f_no_width = 0; + +/*================================================================= + * Static function forward declarations + *=================================================================*/ +void console_registry_level_run(CU_pTestRegistry pRegistry); +static CU_STATUS console_suite_level_run(CU_pSuite pSuite); +static CU_STATUS console_set_options_run(void); + +static CU_ErrorCode console_run_all_tests(CU_pTestRegistry pRegistry); +static CU_ErrorCode console_run_suite(CU_pSuite pSuite); +static CU_ErrorCode console_run_single_test(CU_pSuite pSuite, CU_pTest pTest); + +static void console_test_start_message_handler(const CU_pTest pTest, const CU_pSuite pSuite); +static void console_test_complete_message_handler(const CU_pTest pTest, const CU_pSuite pSuite, const CU_pFailureRecord pFailure); +static void console_all_tests_complete_message_handler(const CU_pFailureRecord pFailure); +static void console_suite_init_failure_message_handler(const CU_pSuite pSuite); +static void console_suite_cleanup_failure_message_handler(const CU_pSuite pSuite); + +static CU_ErrorCode select_test(CU_pSuite pSuite, CU_pTest* ppTest); +static CU_ErrorCode select_suite(CU_pTestRegistry pRegistry, CU_pSuite* ppSuite); + +static void list_suites(CU_pTestRegistry pRegistry); +static void list_tests(CU_pSuite pSuite); +static void show_failures(void); + +/*================================================================= + * Public Interface functions + *=================================================================*/ +void CU_console_run_tests(void) +{ + /* + * To avoid user from cribbing about the output not coming onto + * screen at the moment of SIGSEGV. + */ + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); + + fprintf(stdout, "\n\n %s" CU_VERSION + "\n %s\n", + _("CUnit - A Unit testing framework for C - Version "), + _("http://cunit.sourceforge.net/")); + + if (NULL == CU_get_registry()) { + fprintf(stderr, "\n\n%s\n", _("FATAL ERROR - Test registry is not initialized.")); + CU_set_error(CUE_NOREGISTRY); + } + else { + f_yes_width = strlen(_("Yes")); + f_no_width = strlen(_("No")); + + CU_set_test_start_handler(console_test_start_message_handler); + CU_set_test_complete_handler(console_test_complete_message_handler); + CU_set_all_test_complete_handler(console_all_tests_complete_message_handler); + CU_set_suite_init_failure_handler(console_suite_init_failure_message_handler); + CU_set_suite_cleanup_failure_handler(console_suite_cleanup_failure_message_handler); + + console_registry_level_run(NULL); + } +} + +/*================================================================= + * Static function implementation + *=================================================================*/ +/** + * Main loop for console interface. + * Displays actions and responds based on user imput. If pRegistry + * is NULL, will use the default internal CUnit test registry. + * + * @param pRegistry The CU_pTestRegistry to use for testing. + */ +void console_registry_level_run(CU_pTestRegistry pRegistry) +{ + int chChoice; + CU_pSuite pSuite = NULL; + CU_STATUS eStatus = CU_STATUS_CONTINUE; + char szTemp[256]; + + while (CU_STATUS_CONTINUE == eStatus) + { + fprintf(stdout, "\n\n%s\n%s\n%s", + _("***************************** CUNIT CONSOLE - MAIN MENU *******************************************"), + _("(R)un (S)elect (L)ist (A)ctivate (F)ailures (O)ptions (H)elp (D)rvShell (W)armboot (C)syslog (Q)uit"), + _("Enter command: ")); + chChoice = toupper(getchar()); + if (fgets(szTemp, 256, stdin)); /* flush any chars out of the read buffer */ + + if (chChoice == _("R")[0]) { + console_run_all_tests(pRegistry); + } + + else if (chChoice == _("S")[0]) { + if (CUE_SUCCESS == select_suite(pRegistry, &pSuite)) { + assert(NULL != pSuite->pName); + fprintf(stdout, _("Suite '%s' selected."), pSuite->pName); + fprintf(stdout, "\n"); + if (CU_STATUS_STOP == console_suite_level_run(pSuite)) { + eStatus = CU_STATUS_STOP; + } + } + else { + fprintf(stdout, "\n%s\n", _("Suite not found.")); + } + } + + else if (chChoice == _("L")[0]) { + list_suites(pRegistry); + } + + else if (chChoice == _("A")[0]) { + while (CUE_SUCCESS == select_suite(pRegistry, &pSuite)) { + CU_set_suite_active(pSuite, (CU_FALSE == pSuite->fActive) ? CU_TRUE : CU_FALSE); + } + } + + else if (chChoice == _("F")[0]) { + show_failures(); + } + + else if (chChoice == _("O")[0]) { + console_set_options_run(); + } + + else if (chChoice == _("Q")[0]) { + eStatus = CU_STATUS_STOP; + } + + else if (chChoice == _("D")[0]) { + fprintf(stdout, "Hit enter to get drivshell prompt..\n"); + sai_driver_shell(); + } + + else if (chChoice == _("W")[0]) { + warmboot_enable = warmboot_enable ? 0 : 1; + fprintf(stdout, "Framework changed to run use cases in warmboot %s mode\n", + warmboot_enable ? "enable" : "disable"); + } + + else if (chChoice == _("C")[0]) { + collect_syslog = collect_syslog ? 0 : 1; + fprintf(stdout, "Framework changed to run use cases with syslog collection %s\n", + collect_syslog ? "enable" : "disable"); + } + + else if ((chChoice == _("H")[0]) || (chChoice == _("?")[0])) { + fprintf(stdout, "\n%s\n", _("Commands: R - run all tests in all suites")); + fprintf(stdout, "%s\n", _(" S - Select a suite to run or modify")); + fprintf(stdout, "%s\n", _(" L - List all registered suites")); + fprintf(stdout, "%s\n", _(" A - Activate or deactivate a suite (toggle)")); + fprintf(stdout, "%s\n", _(" F - Show failures from last test run")); + fprintf(stdout, "%s\n", _(" O - Set CUnit options")); + fprintf(stdout, "%s\n", _(" W - Toggle warmboot mode.")); + fprintf(stdout, "%s\n", _(" C - Toggle collect syslog mode")); + fprintf(stdout, "%s\n", _(" H - Show this help message")); + fprintf(stdout, "%s\n", _(" Q - Quit the application")); + } + } +} + +/*------------------------------------------------------------------------*/ +/** + * Runs a selected suite within the console interface. + * Displays actions and responds based on user imput. + * + * @param pSuite The suite to use for testing (non-NULL). + */ +static CU_STATUS console_suite_level_run(CU_pSuite pSuite) +{ + int chChoice; + CU_pTest pTest = NULL; + CU_STATUS eStatus = CU_STATUS_CONTINUE; + char szTemp[256]; + + assert(NULL != pSuite); + assert(NULL != pSuite->pName); + + while (CU_STATUS_CONTINUE == eStatus) { + + fprintf(stdout, "\n%s\n%s\n%s", + _("**************************** CUNIT CONSOLE - SUITE MENU ************************************************"), + _("(R)un (S)elect (L)ist (A)ctivate (F)ailures (U)p (O)ptions (H)elp (D)rvShell (W)armboot (C)syslog (Q)uit"), + _("Enter command: ")); + chChoice = toupper(getchar()); + if (fgets(szTemp, 256, stdin)); /* flush any chars out of the read buffer */ + + if (chChoice == _("R")[0]) { + console_run_suite(pSuite); + } + + else if (chChoice == _("S")[0]) { + if (CUE_SUCCESS == select_test(pSuite, &pTest)) { + console_run_single_test(pSuite, pTest); + } + else { + fprintf(stdout, "\n%s\n", _("Test not found.")); + } + } + + else if (chChoice == _("L")[0]) { + list_tests(pSuite); + } + + else if (chChoice == _("A")[0]) { + while (CUE_SUCCESS == select_test(pSuite, &pTest)) { + CU_set_test_active(pTest, (CU_FALSE == pTest->fActive) ? CU_TRUE : CU_FALSE); + } + } + + else if (chChoice == _("F")[0]) { + show_failures(); + } + + else if ((chChoice == _("M")[0]) || (chChoice == _("U")[0])) { + eStatus = CU_STATUS_MOVE_UP; + } + + else if (chChoice == _("O")[0]) { + console_set_options_run(); + } + + else if (chChoice == _("Q")[0]) { + eStatus = CU_STATUS_STOP; + } + + else if (chChoice == _("D")[0]) { + fprintf(stdout, "Hit enter to get drivshell prompt..\n"); + sai_driver_shell(); + } + + else if (chChoice == _("W")[0]) { + warmboot_enable = warmboot_enable ? 0 : 1; + fprintf(stdout, "Framework changed to run use cases in warmboot %s mode\n", + warmboot_enable ? "enable" : "disable"); + } + + else if (chChoice == _("C")[0]) { + collect_syslog = collect_syslog ? 0 : 1; + fprintf(stdout, "Framework changed to run use cases with syslog collection %s\n", + collect_syslog ? "enable" : "disable"); + } + + else if ((chChoice == _("H")[0]) || (chChoice == _("?")[0])) { + fprintf(stdout, "\n"); + fprintf(stdout, _("Commands: R - run all tests in suite %s"), pSuite->pName); + fprintf(stdout, "\n"); + fprintf(stdout, "%s\n", _(" S - Select and run a test")); + fprintf(stdout, _(" L - List all tests registered in suite %s"), pSuite->pName); + fprintf(stdout, "\n"); + fprintf(stdout, "%s\n", _(" A - Activate or deactivate a test (toggle)")); + fprintf(stdout, "%s\n", _(" F - Show failures from last test run")); + fprintf(stdout, "%s\n", _(" M - Move up to main menu")); + fprintf(stdout, "%s\n", _(" O - Set CUnit options")); + fprintf(stdout, "%s\n", _(" W - Toggle warmboot mode.")); + fprintf(stdout, "%s\n", _(" C - Toggle collect syslog mode")); + fprintf(stdout, "%s\n", _(" H - Show this help message")); + fprintf(stdout, "%s\n", _(" Q - Quit the application")); + } + } + return eStatus; +} + +/*------------------------------------------------------------------------*/ +/** + * Sets CUnit options interactively using console interface. + * Displays actions and responds based on user imput. + */ +static CU_STATUS console_set_options_run(void) +{ + int chChoice; + CU_STATUS eStatus = CU_STATUS_CONTINUE; + char szTemp[256]; + + while (CU_STATUS_CONTINUE == eStatus) { + fprintf(stdout, "\n%s\n", + _("***************** CUNIT CONSOLE - OPTIONS **************************")); + fprintf(stdout, _(" 1 - Inactive suites/tests treated as runtime failures %s"), + (CU_FALSE != CU_get_fail_on_inactive()) ? _("Yes") : _("No")); + fprintf(stdout, "\n********************************************************************\n"); + fprintf(stdout, "%s", + _("Enter number of option to change : ")); + chChoice = getchar(); + if (fgets(szTemp, 256, stdin)); /* flush any chars out of the read buffer */ + + switch (tolower(chChoice)) { + case '1': + CU_set_fail_on_inactive((CU_FALSE == CU_get_fail_on_inactive()) ? CU_TRUE : CU_FALSE); + break; + + default: + eStatus = CU_STATUS_MOVE_UP; + break; + } + } + return eStatus; +} + +/*------------------------------------------------------------------------*/ +/** + * Runs all tests within the console interface. + * The test registry is changed to the specified registry before running + * the tests, and reset to the original registry when done. If pRegistry + * is NULL, the default internal CUnit test registry is used. + * + * @param pRegistry The CU_pTestRegistry containing the tests to be run. + * @return An error code indicating the error status during the test run. + */ +static CU_ErrorCode console_run_all_tests(CU_pTestRegistry pRegistry) +{ + CU_pTestRegistry pOldRegistry = NULL; + CU_ErrorCode result; + + f_pRunningSuite = NULL; + + if (NULL != pRegistry) { + pOldRegistry = CU_set_registry(pRegistry); + } + result = CU_run_all_tests(); + if (NULL != pRegistry) { + CU_set_registry(pOldRegistry); + } + return result; +} + +/*------------------------------------------------------------------------*/ +/** + * Runs a specified suite within the console interface. + * + * @param pSuite The suite to be run (non-NULL). + * @return An error code indicating the error status during the test run. + */ +static CU_ErrorCode console_run_suite(CU_pSuite pSuite) +{ + f_pRunningSuite = NULL; + return CU_run_suite(pSuite); +} + +/*------------------------------------------------------------------------*/ +/** + ( Runs a specific test for the specified suite within the console interface. + * + * @param pSuite The suite containing the test to be run (non-NULL). + * @param pTest The test to be run (non-NULL). + * @return An error code indicating the error status during the test run. + */ +static CU_ErrorCode console_run_single_test(CU_pSuite pSuite, CU_pTest pTest) +{ + f_pRunningSuite = NULL; + return CU_run_test(pSuite, pTest); +} + +/*------------------------------------------------------------------------*/ +/** + * Reads the number of a test from standard input and locates the test + * at that position. A pointer to the located test is stored + * in ppTest upon return. + * + * @param pSuite The suite to be queried. + * @param ppTest Pointer to location to store the selected test. + * @return CUE_SUCCESS if a test was successfully selected, CUE_NOTEST + * otherwise. On return, ppTest points to the test selected, + * or NULL if none. + */ +static CU_ErrorCode select_test(CU_pSuite pSuite, CU_pTest* ppTest) +{ + char buffer[100]; + + assert(NULL != pSuite); + assert(NULL != pSuite->pName); + *ppTest = NULL; + + if (0 == pSuite->uiNumberOfTests) { + fprintf(stdout, "\n"); + fprintf(stdout, _("Suite %s contains no tests."), pSuite->pName); + } + else { + list_tests(pSuite); + fprintf(stdout, "\n"); + fprintf(stdout, _("Enter number of test to select (1-%u) : "), + pSuite->uiNumberOfTests); + if (fgets(buffer, 100, stdin)); + + *ppTest = CU_get_test_by_index(atol(buffer), pSuite); + } + + return (NULL != *ppTest) ? CUE_SUCCESS : CUE_NOTEST; +} + +/*------------------------------------------------------------------------*/ +/** + * Reads the number of a suite from standard input and locates the suite + * at that position. If pRegistry is NULL, the default CUnit registry + * will be used. The located pSuite is returned in ppSuite. ppSuite + * will be NULL if there is no suite in the registry having the input name. + * Returns NULL if the suite is successfully located, non-NULL otherwise. + * + * @param pRegistry The CU_pTestRegistry to query. If NULL, use the + * default internal CUnit test registry. + * @param ppSuite Pointer to location to store the selected suite. + * @return CUE_SUCCESS if a suite was successfully selected, CUE_NOSUITE + * otherwise. On return, ppSuite points to the suite selected. + */ +static CU_ErrorCode select_suite(CU_pTestRegistry pRegistry, CU_pSuite* ppSuite) +{ + char buffer[100]; + + if (NULL == pRegistry) { + pRegistry = CU_get_registry(); + } + + if (0 == pRegistry->uiNumberOfSuites) { + fprintf(stdout, "\n%s", _("No suites are registered.")); + *ppSuite = NULL; + } + else { + list_suites(pRegistry); + fprintf(stdout, "\n"); + fprintf(stdout, _("Enter number of suite to select (1-%u) : "), + pRegistry->uiNumberOfSuites); + if (fgets(buffer, 100, stdin)); + + *ppSuite = CU_get_suite_by_index(atol(buffer), pRegistry); + } + + return (NULL != *ppSuite) ? CUE_SUCCESS : CUE_NOSUITE; +} + +/*------------------------------------------------------------------------*/ +/** + * Lists the suites in a registry to standard output. + * @param pRegistry The CU_pTestRegistry to query (non-NULL). + */ +static void list_suites(CU_pTestRegistry pRegistry) +{ + CU_pSuite pCurSuite = NULL; + int i; + static int width[6]; + + if (NULL == pRegistry) { + pRegistry = CU_get_registry(); + } + + assert(NULL != pRegistry); + if (0 == pRegistry->uiNumberOfSuites) { + fprintf(stdout, "\n%s\n", _("No suites are registered.")); + return; + } + + assert(NULL != pRegistry->pSuite); + + /* only need to calculate formatting widths once */ + if (0 == width[0]) { + width[0] = CU_number_width(pRegistry->uiNumberOfSuites) + 1; + width[1] = 34; + width[2] = CU_MAX(strlen(_("Init?")), CU_MAX(f_yes_width, f_no_width)) + 1; + width[3] = CU_MAX(strlen(_("Cleanup?")), CU_MAX(f_yes_width, f_no_width)) + 1; + width[4] = CU_MAX(strlen(_("#Tests")), CU_number_width(pRegistry->uiNumberOfTests) + 1) + 1; + width[5] = CU_MAX(strlen(_("Active?")), CU_MAX(f_yes_width, f_no_width)) + 1; + } + + fprintf(stdout, "\n%s", _("--------------------- Registered Suites -----------------------------")); + fprintf(stdout, "\n%*s %-*s%*s%*s%*s%*s\n", + width[0], _("#"), + width[1], _("Suite Name"), + width[2], _("Init?"), + width[3], _("Cleanup?"), + width[4], _("#Tests"), + width[5], _("Active?")); + + for (i = 1, pCurSuite = pRegistry->pSuite; (NULL != pCurSuite); pCurSuite = pCurSuite->pNext, ++i) { + assert(NULL != pCurSuite->pName); + fprintf(stdout, "\n%*d. %-*.*s%*s%*s%*u%*s", + width[0], i, + width[1], width[1] - 1, pCurSuite->pName, + width[2]-1, (NULL != pCurSuite->pInitializeFunc) ? _("Yes") : _("No"), + width[3], (NULL != pCurSuite->pCleanupFunc) ? _("Yes") : _("No"), + width[4], pCurSuite->uiNumberOfTests, + width[5], (CU_FALSE != pCurSuite->fActive) ? _("Yes") : _("No")); + } + fprintf(stdout, "\n---------------------------------------------------------------------\n"); + fprintf(stdout, _("Total Number of Suites : %-u"), pRegistry->uiNumberOfSuites); + fprintf(stdout, "\n"); +} + +/*------------------------------------------------------------------------*/ +/** + * Lists the tests in a suite to standard output. + * @param pSuite The suite to query (non-NULL). + */ +static void list_tests(CU_pSuite pSuite) +{ + CU_pTest pCurTest = NULL; + unsigned int uiCount; + static int width[3]; + + assert(NULL != pSuite); + assert(NULL != pSuite->pName); + + if (0 == pSuite->uiNumberOfTests) { + fprintf(stdout, "\n"); + fprintf(stdout, _("Suite %s contains no tests."), pSuite->pName); + fprintf(stdout, "\n"); + return; + } + + assert(NULL != pSuite->pTest); + + /* only number of tests can change between calls */ + width[0] = CU_number_width(pSuite->uiNumberOfTests) + 1; + if (0 == width[1]) { + width[1] = 34; + width[2] = CU_MAX(strlen(_("Active?")), CU_MAX(f_yes_width, f_no_width)) + 1; + } + + fprintf(stdout, "\n%s", + _("----------------- Test List ------------------------------")); + fprintf(stdout, "\n%s%s\n", _("Suite: "), pSuite->pName); + fprintf(stdout, "\n%*s %-*s%*s\n", + width[0], _("#"), + width[1], _("Test Name"), + width[2], _("Active?")); + + for (uiCount = 1, pCurTest = pSuite->pTest ; + NULL != pCurTest ; + uiCount++, pCurTest = pCurTest->pNext) { + assert(NULL != pCurTest->pName); + fprintf(stdout, "\n%*u. %-*.*s%*s", + width[0], uiCount, + width[1], width[1]-1, pCurTest->pName, + width[2]-1, (CU_FALSE != pCurTest->fActive) ? _("Yes") : _("No")); + } + fprintf(stdout, "\n----------------------------------------------------------\n"); + fprintf(stdout, _("Total Number of Tests : %-u"), pSuite->uiNumberOfTests); + fprintf(stdout, "\n"); +} + +/*------------------------------------------------------------------------*/ +/** Displays the record of test failures on standard output. */ +static void show_failures(void) +{ + unsigned int i; + CU_pFailureRecord pFailure = CU_get_failure_list(); + + if (NULL == pFailure) { + fprintf(stdout, "\n%s\n", _("No failures.")); + } + else { + + fprintf(stdout, "\n%s", + _("--------------- Test Run Failures -------------------------")); + fprintf(stdout, "\n%s\n", + _(" src_file:line# : (suite:test) : failure_condition")); + + for (i = 1 ; (NULL != pFailure) ; pFailure = pFailure->pNext, i++) { + fprintf(stdout, "\n%d. %s:%u : (%s : %s) : %s", i, + (NULL != pFailure->strFileName) + ? pFailure->strFileName : "", + pFailure->uiLineNumber, + ((NULL != pFailure->pSuite) && (NULL != pFailure->pSuite->pName)) + ? pFailure->pSuite->pName : "", + ((NULL != pFailure->pTest) && (NULL != pFailure->pTest->pName)) + ? pFailure->pTest->pName : "", + (NULL != pFailure->strCondition) + ? pFailure->strCondition : ""); + } + fprintf(stdout, "\n-----------------------------------------------------------"); + fprintf(stdout, "\n"); + fprintf(stdout, _("Total Number of Failures : %-u"), i - 1); + fprintf(stdout, "\n"); + } +} + +/*------------------------------------------------------------------------*/ +/** Handler function called at start of each test. + * @param pTest The test being run. + * @param pSuite The suite containing the test. + */ +static void console_test_start_message_handler(const CU_pTest pTest, const CU_pSuite pSuite) +{ + assert(NULL != pTest); + assert(NULL != pTest->pName); + assert(NULL != pSuite); + assert(NULL != pSuite->pName); + + /* Comparing the Addresses rather than the Group Names. */ + if ((NULL == f_pRunningSuite) || (f_pRunningSuite != pSuite)) { + fprintf(stdout, _("\nRunning Suite : %s"), pSuite->pName); + fprintf(stdout, _("\n Running Test : %s"), pTest->pName); + f_pRunningSuite = pSuite; + } + else { + fprintf(stdout, _("\n Running Test : %s"), pTest->pName); + } +} + +/*------------------------------------------------------------------------*/ +/** Handler function called at completion of each test. + * @param pTest The test being run. + * @param pSuite The suite containing the test. + * @param pFailure Pointer to the 1st failure record for this test. + */ +static void console_test_complete_message_handler(const CU_pTest pTest, + const CU_pSuite pSuite, + const CU_pFailureRecord pFailure) +{ + /* + * For console interface do nothing. This is useful only for the test + * interface where UI is involved. Just silence compiler warnings. + */ + CU_UNREFERENCED_PARAMETER(pTest); + CU_UNREFERENCED_PARAMETER(pSuite); + CU_UNREFERENCED_PARAMETER(pFailure); +} + +/*------------------------------------------------------------------------*/ +/** Handler function called at completion of all tests in a suite. + * @param pFailure Pointer to the test failure record list. + */ +static void console_all_tests_complete_message_handler(const CU_pFailureRecord pFailure) +{ + CU_UNREFERENCED_PARAMETER(pFailure); /* not used in console interface */ + printf("\n\n"); + CU_print_run_results(stdout); + printf("\n"); +} + +/*------------------------------------------------------------------------*/ +/** Handler function called when suite initialization fails. + * @param pSuite The suite for which initialization failed. + */ +static void console_suite_init_failure_message_handler(const CU_pSuite pSuite) +{ + assert(NULL != pSuite); + assert(NULL != pSuite->pName); + + fprintf(stdout, + _("\nWARNING - Suite initialization failed for '%s'."), pSuite->pName); +} + +/*------------------------------------------------------------------------*/ +/** Handler function called when suite cleanup fails. + * @param pSuite The suite for which cleanup failed. + */ +static void console_suite_cleanup_failure_message_handler(const CU_pSuite pSuite) +{ + assert(NULL != pSuite); + assert(NULL != pSuite->pName); + + fprintf(stdout, _("\nWARNING - Suite cleanup failed for '%s'."), pSuite->pName); +} + +/** @} */ diff --git a/pde-test-host/pde-test-host/cunit/MyMem.c b/pde-test-host/pde-test-host/cunit/MyMem.c new file mode 100755 index 0000000..7ff8a3a --- /dev/null +++ b/pde-test-host/pde-test-host/cunit/MyMem.c @@ -0,0 +1,585 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2001 Anil Kumar + * Copyright (C) 2004-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 + */ + +/* + * Memory management functions used throughout CUnit. + * + * 13/Oct/2001 Moved some of the generic functions definitions from other + * files to this one so as to use the functions consitently. + * This file is not included in the distribution headers because + * it is used internally by CUnit. (AK) + * + * 18-Jul-2004 New interface, doxygen comments, made local functions & + * constants static, fixed reporting of memory tracking (valid + * vs invalid cycles), restructured memory tracking to detect + * reallocations & multiple deletions. (JDS) + * + * 24-Apr-2005 Changed type of allocated sizes to size_t to avoid + * signed-unsigned mismatch. (JDS) + * + * 02-May-2006 Added internationalization hooks. (JDS) + */ + +/** @file + * Memory management & reporting functions (implementation). + */ +/** @addtogroup Framework + @{ +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "CUnit.h" +#include "MyMem.h" +#include "CUnit_intl.h" + +#ifdef MEMTRACE + +#define MAX_FILE_NAME_LENGTH 256 + +/** Default name for memory dump file. */ +static const char* f_szDefaultDumpFileName = "CUnit-Memory-Dump.xml"; +/**< Default name for memory dump file. */ + +#ifdef CUNIT_BUILD_TESTS +/** For testing use (only) to simulate memory exhaustion - + * if CU_FALSE, allocation requests will always fail and return NULL. + */ +static CU_BOOL f_bTestCunitMallocActive = CU_TRUE; +#endif + +/** Structure holding the details of a memory allocation/deallocation event. */ +typedef struct mem_event { + size_t Size; + unsigned int AllocLine; + char AllocFilename[MAX_FILE_NAME_LENGTH]; + unsigned int DeallocLine; + char DeallocFilename[MAX_FILE_NAME_LENGTH]; + struct mem_event* pNext; +} MEMORY_EVENT; +typedef MEMORY_EVENT* PMEMORY_EVENT; + +#define NOT_ALLOCATED 0 +#define NOT_DELETED 0 + +/** Structure holding the details of a memory node having allocation/deallocation events. */ +typedef struct mem_node { + void* pLocation; + unsigned int EventCount; + PMEMORY_EVENT pFirstEvent; + struct mem_node* pNext; +} MEMORY_NODE; +typedef MEMORY_NODE* PMEMORY_NODE; + +static PMEMORY_NODE f_pMemoryTrackerHead = NULL; /**< Head of double-linked list of memory nodes. */ +static unsigned int f_nMemoryNodes = 0; /**< Counter for memory nodes created. */ +/*------------------------------------------------------------------------*/ +/** Locate the memory node for the specified memory location (returns NULL if none). */ +static PMEMORY_NODE find_memory_node(void* pLocation) +{ + PMEMORY_NODE pMemoryNode = f_pMemoryTrackerHead; + while (NULL != pMemoryNode) { + if (pLocation == pMemoryNode->pLocation) { + break; + } + pMemoryNode = pMemoryNode->pNext; + } + + return pMemoryNode; +} +/*------------------------------------------------------------------------*/ +/** Create a new memory node for the specified memory location. */ +static PMEMORY_NODE create_memory_node(void* pLocation) +{ + PMEMORY_NODE pTempNode = NULL; + PMEMORY_NODE pMemoryNode = find_memory_node(pLocation); + + /* a memory node for pLocation should not exist yet */ + if (NULL == pMemoryNode) { + + pMemoryNode = (PMEMORY_NODE)malloc(sizeof(MEMORY_NODE)); + assert(NULL != pMemoryNode); + + pMemoryNode->pLocation = pLocation; + pMemoryNode->EventCount = 0; + pMemoryNode->pFirstEvent = NULL; + pMemoryNode->pNext = NULL; + + /* add new node to linked list */ + pTempNode = f_pMemoryTrackerHead; + if (NULL == pTempNode) { + f_pMemoryTrackerHead = pMemoryNode; + } + else { + while (NULL != pTempNode->pNext) { + pTempNode = pTempNode->pNext; + } + pTempNode->pNext = pMemoryNode; + } + + ++f_nMemoryNodes; + } + return pMemoryNode; +} +/*------------------------------------------------------------------------*/ +/** Add a new memory event having the specified parameters. */ +static PMEMORY_EVENT add_memory_event(PMEMORY_NODE pMemoryNode, + size_t size, + unsigned int alloc_line, + const char* alloc_filename) +{ + PMEMORY_EVENT pMemoryEvent = NULL; + PMEMORY_EVENT pTempEvent = NULL; + + assert (NULL != pMemoryNode); + + /* create and set up the new event */ + pMemoryEvent = (PMEMORY_EVENT)malloc(sizeof(MEMORY_EVENT)); + assert(NULL != pMemoryEvent); + + pMemoryEvent->Size = size; + pMemoryEvent->AllocLine = alloc_line; + strncpy(pMemoryEvent->AllocFilename, alloc_filename, (size_t) MAX_FILE_NAME_LENGTH-1); + pMemoryEvent->AllocFilename[MAX_FILE_NAME_LENGTH-1] = (char)0; + pMemoryEvent->DeallocLine = NOT_DELETED; + pMemoryEvent->DeallocFilename[0] = (char)0; + pMemoryEvent->pNext = NULL; + + /* add the new event to the end of the linked list */ + pTempEvent = pMemoryNode->pFirstEvent; + if (NULL == pTempEvent) { + pMemoryNode->pFirstEvent = pMemoryEvent; + } + else { + while (NULL != pTempEvent->pNext) { + pTempEvent = pTempEvent->pNext; + } + pTempEvent->pNext = pMemoryEvent; + } + + ++pMemoryNode->EventCount; + + return pMemoryEvent; +} +/*------------------------------------------------------------------------*/ +/** Record memory allocation event. */ +static PMEMORY_NODE allocate_memory(size_t nSize, + void* pLocation, + unsigned int uiAllocationLine, + const char* szAllocationFile) +{ + PMEMORY_NODE pMemoryNode = NULL; + + /* attempt to locate an existing record for this pLocation */ + pMemoryNode = find_memory_node(pLocation); + + /* pLocation not found - create a new event record */ + if (NULL == pMemoryNode) { + pMemoryNode = create_memory_node(pLocation); + } + + /* add the new event record */ + add_memory_event(pMemoryNode, nSize, uiAllocationLine, szAllocationFile); + + return pMemoryNode; +} + +/*------------------------------------------------------------------------*/ +/** Record memory deallocation event. */ +static void deallocate_memory(void* pLocation, unsigned int uiDeletionLine, const char* szDeletionFileName) +{ + PMEMORY_NODE pMemoryNode = NULL; + PMEMORY_EVENT pTempEvent = NULL; + + assert(0 != uiDeletionLine); + assert(NULL != szDeletionFileName); + + /* attempt to locate an existing record for this pLocation */ + pMemoryNode = find_memory_node(pLocation); + + /* if no entry, then an unallocated pointer was freed */ + if (NULL == pMemoryNode) { + pMemoryNode = create_memory_node(pLocation); + pTempEvent = add_memory_event(pMemoryNode, 0, NOT_ALLOCATED, ""); + } + else { + /* there should always be at least 1 event for an existing memory node */ + assert(NULL != pMemoryNode->pFirstEvent); + + /* locate last memory event for this pLocation */ + pTempEvent = pMemoryNode->pFirstEvent; + while (NULL != pTempEvent->pNext) { + pTempEvent = pTempEvent->pNext; + } + + /* if pointer has already been freed, create a new event for double deletion */ + if (NOT_DELETED != pTempEvent->DeallocLine) { + pTempEvent = add_memory_event(pMemoryNode, pTempEvent->Size, NOT_ALLOCATED, ""); + } + } + + pTempEvent->DeallocLine = uiDeletionLine; + strncpy(pTempEvent->DeallocFilename, szDeletionFileName, MAX_FILE_NAME_LENGTH-1); + pTempEvent->DeallocFilename[MAX_FILE_NAME_LENGTH-1] = (char)0; +} + +/*------------------------------------------------------------------------*/ +/** Custom calloc function with memory event recording. */ +void* CU_calloc(size_t nmemb, size_t size, unsigned int uiLine, const char* szFileName) +{ + void* pVoid = NULL; + +#ifdef CUNIT_BUILD_TESTS + if (CU_FALSE == f_bTestCunitMallocActive) { + return NULL; + } +#endif + + pVoid = calloc(nmemb, size); + if (NULL != pVoid) { + allocate_memory(nmemb * size, pVoid, uiLine, szFileName); + } + + return pVoid; +} + +/*------------------------------------------------------------------------*/ +/** Custom malloc function with memory event recording. */ +void* CU_malloc(size_t size, unsigned int uiLine, const char* szFileName) +{ + void* pVoid = NULL; + +#ifdef CUNIT_BUILD_TESTS + if (CU_FALSE == f_bTestCunitMallocActive) { + return NULL; + } +#endif + + pVoid = malloc(size); + if (NULL != pVoid) { + allocate_memory(size, pVoid, uiLine, szFileName); + } + + return pVoid; +} + +/*------------------------------------------------------------------------*/ +/** Custom free function with memory event recording. */ +void CU_free(void *ptr, unsigned int uiLine, const char* szFileName) +{ + deallocate_memory(ptr, uiLine, szFileName); + free(ptr); +} + +/*------------------------------------------------------------------------*/ +/** Custom realloc function with memory event recording. */ +void* CU_realloc(void *ptr, size_t size, unsigned int uiLine, const char* szFileName) +{ + void* pVoid = NULL; + + deallocate_memory(ptr, uiLine, szFileName); + +#ifdef CUNIT_BUILD_TESTS + if (CU_FALSE == f_bTestCunitMallocActive) { + free(ptr); + return NULL; + } +#endif + + pVoid = realloc(ptr, size); + + if (NULL != pVoid) { + allocate_memory(size, pVoid, uiLine, szFileName); + } + + return pVoid; +} + +/*------------------------------------------------------------------------*/ +/** Print a report of memory events to file. */ +void CU_dump_memory_usage(const char* szFilename) +{ + char* szDumpFileName = (char*)f_szDefaultDumpFileName; + unsigned int nValid; + unsigned int nInvalid; + PMEMORY_NODE pTempNode = NULL; + PMEMORY_EVENT pTempEvent = NULL; + FILE* pFile = NULL; + time_t tTime = 0; + + /* use the specified file name, if supplied) */ + if ((NULL != szFilename) && strlen(szFilename) > 0) { + szDumpFileName = (char*)szFilename; + } + + if (NULL == (pFile = fopen(szDumpFileName, "w"))) { + fprintf(stderr, _("Failed to open file \"%s\" : %s"), szDumpFileName, strerror(errno)); + return; + } + + setvbuf(pFile, NULL, _IONBF, 0); + + fprintf(pFile, "<\?xml version=\"1.0\" \?>"); + fprintf(pFile, "\n<\?xml-stylesheet type=\"text/xsl\" href=\"Memory-Dump.xsl\" \?>"); + fprintf(pFile, "\n"); + fprintf(pFile, "\n"); + fprintf(pFile, "\n "); + fprintf(pFile, "\n "); + + nValid = 0; + nInvalid = 0; + pTempNode = f_pMemoryTrackerHead; + while (NULL != pTempNode) { + fprintf(pFile, "\n "); + fprintf(pFile, "\n %p ", pTempNode->pLocation); + fprintf(pFile, "\n %u ", pTempNode->EventCount); + + pTempEvent = pTempNode->pFirstEvent; + while (NULL != pTempEvent) { + fprintf(pFile, "\n "); + fprintf(pFile, "\n %u ", pTempEvent->Size); + fprintf(pFile, "\n %s ", pTempEvent->AllocFilename); + fprintf(pFile, "\n %u ", pTempEvent->AllocLine); + fprintf(pFile, "\n %s ", pTempEvent->DeallocFilename); + fprintf(pFile, "\n %u ", pTempEvent->DeallocLine); + fprintf(pFile, "\n "); + + if ((0 != pTempEvent->AllocLine) && (0 != pTempEvent->DeallocLine)) { + ++nValid; + } + else { + ++nInvalid; + } + + pTempEvent = pTempEvent->pNext; + } + + fprintf(pFile, "\n "); + pTempNode = pTempNode->pNext; + } + + fprintf(pFile, "\n "); + + fprintf(pFile, "\n "); + fprintf(pFile, "\n %u ", nValid); + fprintf(pFile, "\n %u ", nInvalid); + fprintf(pFile, "\n %u ", nValid + nInvalid); + fprintf(pFile, "\n "); + + time(&tTime); + fprintf(pFile, "\n Memory Trace for CUnit Run at %s ", ctime(&tTime)); + fprintf(pFile, ""); + + fclose(pFile); +} + +#endif /* MEMTRACE */ + +/** @} */ + +#ifdef CUNIT_BUILD_TESTS +#include "test_cunit.h" + +/** Deactivate CUnit memory allocation + * After calling this function, all Cunit memory + * allocation routines will fail and return NULL. + */ +void test_cunit_deactivate_malloc(void) +{ + f_bTestCunitMallocActive = CU_FALSE; +} + +/** Activate CUnit memory allocation + * After calling this function, all Cunit memory + * allocation routines will behave normally (allocating + * memory if it is available). + */ +void test_cunit_activate_malloc(void) +{ + f_bTestCunitMallocActive = CU_TRUE; +} + +/** Retrieve the number of memory events recorded for a given pointer. */ +unsigned int test_cunit_get_n_memevents(void* pLocation) +{ + PMEMORY_NODE pNode = find_memory_node(pLocation); + return (pNode) ? pNode->EventCount : 0; +} + +/** Retrieve the number of memory allocations recorded for a given pointer. */ +unsigned int test_cunit_get_n_allocations(void* pLocation) +{ + PMEMORY_NODE pNode = find_memory_node(pLocation); + PMEMORY_EVENT pEvent = NULL; + int result = 0; + + if (NULL != pNode) { + pEvent = pNode->pFirstEvent; + while (NULL != pEvent) { + if (pEvent->AllocLine != NOT_ALLOCATED) + ++result; + pEvent = pEvent->pNext; + } + } + + return result; +} + +/** Retrieve the number of memory deallocations recorded for a given pointer. */ +unsigned int test_cunit_get_n_deallocations(void* pLocation) +{ + PMEMORY_NODE pNode = find_memory_node(pLocation); + PMEMORY_EVENT pEvent = NULL; + int result = 0; + + if (NULL != pNode) { + pEvent = pNode->pFirstEvent; + while (NULL != pEvent) { + if (pEvent->DeallocLine != NOT_DELETED) + ++result; + pEvent = pEvent->pNext; + } + } + + return result; +} + +void test_CU_calloc(void) +{ + void* ptr1 = NULL; + void* ptr2 = calloc(2, sizeof(int)); + unsigned int n2 = test_cunit_get_n_memevents(ptr2); + + /* test allocation failure */ + test_cunit_deactivate_malloc(); + ptr1 = CU_CALLOC(2, sizeof(int)); + TEST(NULL == ptr1); + TEST(test_cunit_get_n_allocations(ptr1) == test_cunit_get_n_deallocations(ptr1)); + TEST(test_cunit_get_n_allocations(ptr2) == test_cunit_get_n_deallocations(ptr2)); + test_cunit_activate_malloc(); + + /* normal allocation */ + ptr1 = CU_CALLOC(2, sizeof(int)); + TEST_FATAL(NULL != ptr1); + TEST(test_cunit_get_n_allocations(ptr1) != test_cunit_get_n_deallocations(ptr1)); + TEST(test_cunit_get_n_allocations(ptr2) == test_cunit_get_n_deallocations(ptr2)); + + CU_FREE(ptr1); + TEST(test_cunit_get_n_allocations(ptr1) == test_cunit_get_n_deallocations(ptr1)); + TEST(test_cunit_get_n_allocations(ptr2) == test_cunit_get_n_deallocations(ptr2)); + TEST(n2 == test_cunit_get_n_memevents(ptr2)); + + free(ptr2); +} + +void test_CU_malloc(void) +{ + void* ptr1 = NULL; + void* ptr2 = malloc(sizeof(int)); + unsigned int n2 = test_cunit_get_n_memevents(ptr2); + + /* test allocation failure */ + test_cunit_deactivate_malloc(); + ptr1 = CU_MALLOC(sizeof(int)); + TEST(NULL == ptr1); + TEST(test_cunit_get_n_allocations(ptr1) == test_cunit_get_n_deallocations(ptr1)); + TEST(test_cunit_get_n_allocations(ptr2) == test_cunit_get_n_deallocations(ptr2)); + test_cunit_activate_malloc(); + + /* normal allocation */ + ptr1 = CU_MALLOC(sizeof(int)); + TEST_FATAL(NULL != ptr1); + TEST(test_cunit_get_n_allocations(ptr1) != test_cunit_get_n_deallocations(ptr1)); + TEST(test_cunit_get_n_allocations(ptr2) == test_cunit_get_n_deallocations(ptr2)); + + CU_FREE(ptr1); + TEST(test_cunit_get_n_allocations(ptr1) == test_cunit_get_n_deallocations(ptr1)); + TEST(test_cunit_get_n_allocations(ptr2) == test_cunit_get_n_deallocations(ptr2)); + TEST(n2 == test_cunit_get_n_memevents(ptr2)); + + free(ptr2); +} + +void test_CU_free(void) +{ + /* covered by other test functions */ +} + +void test_CU_realloc(void) +{ + void* ptr1 = CU_MALLOC(sizeof(int)); + void* ptr2 = malloc(sizeof(int)); + void* ptr3; + void* ptr4; + unsigned int n2 = test_cunit_get_n_memevents(ptr2); + + /* test allocation failure */ + test_cunit_deactivate_malloc(); + ptr1 = CU_REALLOC(ptr1, sizeof(long int)); + TEST(NULL == ptr1); + TEST(test_cunit_get_n_allocations(ptr1) == test_cunit_get_n_deallocations(ptr1)); + TEST(test_cunit_get_n_allocations(ptr2) == test_cunit_get_n_deallocations(ptr2)); + test_cunit_activate_malloc(); + + /* normal allocation */ + ptr3 = CU_MALLOC(sizeof(int)); + TEST_FATAL(NULL != ptr3); + TEST(test_cunit_get_n_allocations(ptr1) == test_cunit_get_n_deallocations(ptr1)); + TEST(test_cunit_get_n_allocations(ptr2) == test_cunit_get_n_deallocations(ptr2)); + TEST(test_cunit_get_n_allocations(ptr3) != test_cunit_get_n_deallocations(ptr3)); + + ptr4 = CU_REALLOC(ptr3, sizeof(long int)); + TEST_FATAL(NULL != ptr4); + TEST(test_cunit_get_n_allocations(ptr1) == test_cunit_get_n_deallocations(ptr1)); + TEST(test_cunit_get_n_allocations(ptr2) == test_cunit_get_n_deallocations(ptr2)); + if (ptr3 != ptr4) + TEST(test_cunit_get_n_allocations(ptr3) == test_cunit_get_n_deallocations(ptr3)); + TEST(test_cunit_get_n_allocations(ptr4) != test_cunit_get_n_deallocations(ptr4)); + + CU_FREE(ptr4); + TEST(test_cunit_get_n_allocations(ptr1) == test_cunit_get_n_deallocations(ptr1)); + TEST(test_cunit_get_n_allocations(ptr2) == test_cunit_get_n_deallocations(ptr2)); + TEST(test_cunit_get_n_allocations(ptr3) == test_cunit_get_n_deallocations(ptr3)); + TEST(test_cunit_get_n_allocations(ptr4) == test_cunit_get_n_deallocations(ptr4)); + TEST(n2 == test_cunit_get_n_memevents(ptr2)); + + free(ptr2); +} + +/** The main internal testing function for MyMem.c. */ +void test_cunit_MyMem(void) +{ + test_cunit_start_tests("MyMem.c"); + + test_CU_calloc(); + test_CU_malloc(); + test_CU_free(); + test_CU_realloc(); + + test_cunit_end_tests(); +} + +#endif /* CUNIT_BUILD_TESTS */ diff --git a/pde-test-host/pde-test-host/cunit/TestDB.c b/pde-test-host/pde-test-host/cunit/TestDB.c new file mode 100755 index 0000000..d609f50 --- /dev/null +++ b/pde-test-host/pde-test-host/cunit/TestDB.c @@ -0,0 +1,2773 @@ +/* + * 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 Registry/TestGroup/Testcase management Routines. + * + * Aug 2001 Initial implementation (AK) + * + * 09/Aug/2001 Added startup initialize/cleanup registry functions. (AK) + * + * 29/Aug/2001 Added Test and Group Add functions. (AK) + * + * 02/Oct/2001 Added Proper Error codes and Messages on the failure conditions. (AK) + * + * 13/Oct/2001 Added Code to Check for the Duplicate Group name and test name. (AK) + * + * 15-Jul-2004 Added doxygen comments, new interface, added assertions to + * internal functions, moved error handling code to CUError.c, + * added assertions to make sure no modification of registry + * during a run, bug fixes, changed CU_set_registry() so that it + * doesn't require cleaning the existing registry. (JDS) + * + * 24-Apr-2006 Removed constraint that suites/tests be uniquely named. + * Added ability to turn individual tests/suites on or off. + * Added lookup functions for suites/tests based on index. + * Moved doxygen comments for public API here to header. + * Modified internal unit tests to include these changes. (JDS) + * + * 02-May-2006 Added internationalization hooks. (JDS) + */ + +/** @file + * Management functions for tests, suites, and the test registry (implementation). + */ +/** @addtogroup Framework + @{ +*/ + +#include +#include +#include +#include +#include + +#include "CUnit.h" +#include "MyMem.h" +#include "TestDB.h" +#include "TestRun.h" +#include "Util.h" +#include "CUnit_intl.h" + +/*================================================================= + * Global/Static Definitions + *=================================================================*/ +static CU_pTestRegistry f_pTestRegistry = NULL; /**< The active internal Test Registry. */ + +/*================================================================= + * Private function forward declarations + *=================================================================*/ +static void cleanup_test_registry(CU_pTestRegistry pRegistry); +static CU_pSuite create_suite(const char* strName, CU_InitializeFunc pInit, CU_CleanupFunc pClean); +static void cleanup_suite(CU_pSuite pSuite); +static void insert_suite(CU_pTestRegistry pRegistry, CU_pSuite pSuite); +static CU_pTest create_test(const char* strName, CU_TestFunc pTestFunc); +static void cleanup_test(CU_pTest pTest); +static void insert_test(CU_pSuite pSuite, CU_pTest pTest); + +static CU_BOOL suite_exists(CU_pTestRegistry pRegistry, const char* szSuiteName); +static CU_BOOL test_exists(CU_pSuite pSuite, const char* szTestName); + +/*================================================================= + * Public Interface functions + *=================================================================*/ +CU_ErrorCode CU_initialize_registry(void) +{ + CU_ErrorCode result; + + assert(CU_FALSE == CU_is_test_running()); + + CU_set_error(result = CUE_SUCCESS); + + if (NULL != f_pTestRegistry) { + CU_cleanup_registry(); + } + + f_pTestRegistry = CU_create_new_registry(); + if (NULL == f_pTestRegistry) { + CU_set_error(result = CUE_NOMEMORY); + } + + return result; +} + +/*------------------------------------------------------------------------*/ +CU_BOOL CU_registry_initialized(void) +{ + return (NULL == f_pTestRegistry) ? CU_FALSE : CU_TRUE; +} + +/*------------------------------------------------------------------------*/ +void CU_cleanup_registry(void) +{ + assert(CU_FALSE == CU_is_test_running()); + + CU_set_error(CUE_SUCCESS); + CU_destroy_existing_registry(&f_pTestRegistry); /* supposed to handle NULL ok */ + CU_clear_previous_results(); + CU_CREATE_MEMORY_REPORT(NULL); +} + +/*------------------------------------------------------------------------*/ +CU_pTestRegistry CU_get_registry(void) +{ + return f_pTestRegistry; +} + +/*------------------------------------------------------------------------*/ +CU_pTestRegistry CU_set_registry(CU_pTestRegistry pRegistry) +{ + CU_pTestRegistry pOldRegistry = f_pTestRegistry; + + assert(CU_FALSE == CU_is_test_running()); + + CU_set_error(CUE_SUCCESS); + f_pTestRegistry = pRegistry; + return pOldRegistry; +} + +/*------------------------------------------------------------------------*/ +CU_pSuite CU_add_suite(const char* strName, CU_InitializeFunc pInit, CU_CleanupFunc pClean) +{ + CU_pSuite pRetValue = NULL; + CU_ErrorCode error = CUE_SUCCESS; + + assert(CU_FALSE == CU_is_test_running()); + + if (NULL == f_pTestRegistry) { + error = CUE_NOREGISTRY; + } + else if (NULL == strName) { + error = CUE_NO_SUITENAME; + } + else { + pRetValue = create_suite(strName, pInit, pClean); + if (NULL == pRetValue) { + error = CUE_NOMEMORY; + } + else { + if (CU_TRUE == suite_exists(f_pTestRegistry, strName)) { + error = CUE_DUP_SUITE; + } + insert_suite(f_pTestRegistry, pRetValue); + } + } + + CU_set_error(error); + return pRetValue; +} + +/*------------------------------------------------------------------------*/ +CU_ErrorCode CU_set_suite_active(CU_pSuite pSuite, CU_BOOL fNewActive) +{ + CU_ErrorCode result = CUE_SUCCESS; + + if (NULL == pSuite) { + result = CUE_NOSUITE; + } + else { + pSuite->fActive = fNewActive; + } + + CU_set_error(result); + return result; +} + +/*------------------------------------------------------------------------*/ +CU_ErrorCode CU_set_suite_name(CU_pSuite pSuite, const char *strNewName) +{ + CU_ErrorCode result = CUE_SUCCESS; + + if (NULL == pSuite) { + result = CUE_NOSUITE; + } + else if (NULL == strNewName) { + result = CUE_NO_SUITENAME; + } + else { + CU_FREE(pSuite->pName); + pSuite->pName = (char *)CU_MALLOC(strlen(strNewName)+1); + strcpy(pSuite->pName, strNewName); + } + + CU_set_error(result); + return result; +} + +/*------------------------------------------------------------------------*/ +CU_ErrorCode CU_set_suite_initfunc(CU_pSuite pSuite, CU_InitializeFunc pNewInit) +{ + CU_ErrorCode result = CUE_SUCCESS; + + if (NULL == pSuite) { + result = CUE_NOSUITE; + } + else { + pSuite->pInitializeFunc = pNewInit; + } + + CU_set_error(result); + return result; +} + +/*------------------------------------------------------------------------*/ +CU_ErrorCode CU_set_suite_cleanupfunc(CU_pSuite pSuite, CU_CleanupFunc pNewClean) +{ + CU_ErrorCode result = CUE_SUCCESS; + + if (NULL == pSuite) { + result = CUE_NOSUITE; + } + else { + pSuite->pCleanupFunc = pNewClean; + } + + CU_set_error(result); + return result; +} + +/*------------------------------------------------------------------------*/ +CU_pSuite CU_get_suite(const char *strName) +{ + CU_pSuite result = NULL; + CU_ErrorCode error = CUE_SUCCESS; + + if (NULL == f_pTestRegistry) { + error = CUE_NOREGISTRY; + } + else if (NULL == strName) { + error = CUE_NO_SUITENAME; + } + else { + result = CU_get_suite_by_name(strName, f_pTestRegistry); + } + + CU_set_error(error); + return result; +} + +/*------------------------------------------------------------------------*/ +CU_pSuite CU_get_suite_at_pos(unsigned int pos) +{ + CU_pSuite result = NULL; + CU_ErrorCode error = CUE_SUCCESS; + + if (NULL == f_pTestRegistry) { + error = CUE_NOREGISTRY; + } + else { + result = CU_get_suite_by_index(pos, f_pTestRegistry); + } + + CU_set_error(error); + return result; +} + +/*------------------------------------------------------------------------*/ +unsigned int CU_get_suite_pos(CU_pSuite pSuite) +{ + unsigned int result = 0; + CU_ErrorCode error = CUE_SUCCESS; + CU_pSuite pCurrentSuite = NULL; + + if (NULL == f_pTestRegistry) { + error = CUE_NOREGISTRY; + } + else if (NULL == pSuite) { + error = CUE_NOSUITE; + } + else { + pCurrentSuite = f_pTestRegistry->pSuite; + result = 1; + while ((NULL != pCurrentSuite) && (pCurrentSuite != pSuite)) { + ++result; + pCurrentSuite = pCurrentSuite->pNext; + } + if (pCurrentSuite == NULL) { + result = 0; + } + } + + CU_set_error(error); + return result; +} + +/*------------------------------------------------------------------------*/ +unsigned int CU_get_suite_pos_by_name(const char *strName) +{ + unsigned int result = 0; + CU_ErrorCode error = CUE_SUCCESS; + CU_pSuite pCurrentSuite = NULL; + + if (NULL == f_pTestRegistry) { + error = CUE_NOREGISTRY; + } + else if (NULL == strName) { + error = CUE_NO_SUITENAME; + } + else { + pCurrentSuite = f_pTestRegistry->pSuite; + result = 1; + while ((NULL != pCurrentSuite) && (0 != strcmp(pCurrentSuite->pName, strName))) { + ++result; + pCurrentSuite = pCurrentSuite->pNext; + } + if (pCurrentSuite == NULL) { + result = 0; + } + } + + CU_set_error(error); + return result; +} + +/*------------------------------------------------------------------------*/ +CU_pTest CU_add_test(CU_pSuite pSuite, const char* strName, CU_TestFunc pTestFunc) +{ + CU_pTest pRetValue = NULL; + CU_ErrorCode error = CUE_SUCCESS; + + assert(CU_FALSE == CU_is_test_running()); + + if (NULL == f_pTestRegistry) { + error = CUE_NOREGISTRY; + } + else if (NULL == pSuite) { + error = CUE_NOSUITE; + } + else if (NULL == strName) { + error = CUE_NO_TESTNAME; + } + else if(NULL == pTestFunc) { + error = CUE_NOTEST; + } + else { + pRetValue = create_test(strName, pTestFunc); + if (NULL == pRetValue) { + error = CUE_NOMEMORY; + } + else { + f_pTestRegistry->uiNumberOfTests++; + if (CU_TRUE == test_exists(pSuite, strName)) { + error = CUE_DUP_TEST; + } + insert_test(pSuite, pRetValue); + } + } + + CU_set_error(error); + return pRetValue; +} + +/*------------------------------------------------------------------------*/ +CU_ErrorCode CU_set_test_active(CU_pTest pTest, CU_BOOL fNewActive) +{ + CU_ErrorCode result = CUE_SUCCESS; + + if (NULL == pTest) { + result = CUE_NOTEST; + } + else { + pTest->fActive = fNewActive; + } + + CU_set_error(result); + return result; +} + +/*------------------------------------------------------------------------*/ +CU_ErrorCode CU_set_test_name(CU_pTest pTest, const char *strNewName) +{ + CU_ErrorCode result = CUE_SUCCESS; + + if (NULL == pTest) { + result = CUE_NOTEST; + } + else if (NULL == strNewName) { + result = CUE_NO_TESTNAME; + } + else { + CU_FREE(pTest->pName); + pTest->pName = (char *)CU_MALLOC(strlen(strNewName)+1); + strcpy(pTest->pName, strNewName); + } + + CU_set_error(result); + return result; +} + +/*------------------------------------------------------------------------*/ +CU_ErrorCode CU_set_test_func(CU_pTest pTest, CU_TestFunc pNewFunc) +{ + CU_ErrorCode result = CUE_SUCCESS; + + if ((NULL == pTest) || (NULL == pNewFunc)) { + result = CUE_NOTEST; + } + else { + pTest->pTestFunc = pNewFunc; + } + + CU_set_error(result); + return result; +} + +/*------------------------------------------------------------------------*/ +CU_pTest CU_get_test(CU_pSuite pSuite, const char *strName) +{ + CU_pTest result = NULL; + CU_ErrorCode error = CUE_SUCCESS; + + if (NULL == f_pTestRegistry) { + error = CUE_NOREGISTRY; + } + else if (NULL == pSuite) { + error = CUE_NOSUITE; + } + else if (NULL == strName) { + error = CUE_NO_SUITENAME; + } + else { + result = CU_get_test_by_name(strName, pSuite); + } + + CU_set_error(error); + return result; +} + +/*------------------------------------------------------------------------*/ +CU_pTest CU_get_test_at_pos(CU_pSuite pSuite, unsigned int pos) +{ + CU_pTest result = NULL; + CU_ErrorCode error = CUE_SUCCESS; + + if (NULL == f_pTestRegistry) { + error = CUE_NOREGISTRY; + } + else if (NULL == pSuite) { + error = CUE_NOSUITE; + } + else { + result = CU_get_test_by_index(pos, pSuite); + } + + CU_set_error(error); + return result; +} + +/*------------------------------------------------------------------------*/ +unsigned int CU_get_test_pos(CU_pSuite pSuite, CU_pTest pTest) +{ + unsigned int result = 0; + CU_ErrorCode error = CUE_SUCCESS; + CU_pTest pCurrentTest = NULL; + + if (NULL == f_pTestRegistry) { + error = CUE_NOREGISTRY; + } + else if (NULL == pSuite) { + error = CUE_NOSUITE; + } + else if (NULL == pTest) { + error = CUE_NOTEST; + } + else { + pCurrentTest = pSuite->pTest; + result = 1; + while ((NULL != pCurrentTest) && (pCurrentTest != pTest)) { + ++result; + pCurrentTest = pCurrentTest->pNext; + } + if (pCurrentTest == NULL) { + result = 0; + } + } + + CU_set_error(error); + return result; +} + +/*------------------------------------------------------------------------*/ +unsigned int CU_get_test_pos_by_name(CU_pSuite pSuite, const char *strName) +{ + unsigned int result = 0; + CU_ErrorCode error = CUE_SUCCESS; + CU_pTest pCurrentTest = NULL; + + if (NULL == f_pTestRegistry) { + error = CUE_NOREGISTRY; + } + else if (NULL == pSuite) { + error = CUE_NOSUITE; + } + else if (NULL == strName) { + error = CUE_NO_TESTNAME; + } + else { + pCurrentTest = pSuite->pTest; + result = 1; + while ((NULL != pCurrentTest) && (0 != strcmp(pCurrentTest->pName, strName))) { + ++result; + pCurrentTest = pCurrentTest->pNext; + } + if (pCurrentTest == NULL) { + result = 0; + } + } + + CU_set_error(error); + return result; +} + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +/* This section is based conceptually on code + * Copyright (C) 2004 Aurema Pty Ltd. + * + * 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 + * + * Derived from code contributed by K. Cheung and Aurema Pty Ltd. (thanks!) + * int test_group_register(test_group_t *tg) + * int test_suite_register(test_suite_t *ts) + */ +/*------------------------------------------------------------------------*/ +CU_ErrorCode CU_register_nsuites(int suite_count, ...) +{ + CU_SuiteInfo *pSuiteItem = NULL; + CU_TestInfo *pTestItem = NULL; + CU_pSuite pSuite = NULL; + + va_list argptr; + int i; + + va_start(argptr, suite_count); + + for (i=0 ; ipName; pSuiteItem++) { + if (NULL != (pSuite = CU_add_suite(pSuiteItem->pName, pSuiteItem->pInitFunc, pSuiteItem->pCleanupFunc))) { + for (pTestItem = pSuiteItem->pTests; NULL != pTestItem->pName; pTestItem++) { + if (NULL == CU_add_test(pSuite, pTestItem->pName, pTestItem->pTestFunc)) { + return CU_get_error(); + } + } + } + else { + return CU_get_error(); + } + } + } + } + return CU_get_error(); +} + +/*------------------------------------------------------------------------*/ +CU_ErrorCode CU_register_suites(CU_SuiteInfo suite_info[]) +{ + return CU_register_nsuites(1, suite_info); +} +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +/*================================================================= + * Private static function definitions + *=================================================================*/ +/*------------------------------------------------------------------------*/ +/** + * Internal function to clean up the specified test registry. + * cleanup_suite() will be called for each registered suite to perform + * cleanup of the associated test cases. Then, the suite's memory will + * be freed. Note that any pointers to tests or suites in pRegistry + * held by the user will be invalidated by this function. Severe problems + * can occur if this function is called during a test run involving pRegistry. + * Note that memory held for data members in the registry (e.g. pName) and + * the registry itself are not freed by this function. + * + * @see cleanup_suite() + * @see cleanup_test() + * @param pRegistry CU_pTestRegistry to clean up (non-NULL). + */ +static void cleanup_test_registry(CU_pTestRegistry pRegistry) +{ + CU_pSuite pCurSuite = NULL; + CU_pSuite pNextSuite = NULL; + + assert(NULL != pRegistry); + + pCurSuite = pRegistry->pSuite; + while (NULL != pCurSuite) { + pNextSuite = pCurSuite->pNext; + cleanup_suite(pCurSuite); + + CU_FREE(pCurSuite); + pCurSuite = pNextSuite; + } + pRegistry->pSuite = NULL; + pRegistry->uiNumberOfSuites = 0; + pRegistry->uiNumberOfTests = 0; +} + +/*------------------------------------------------------------------------*/ +/** + * Internal function to create a new test suite having the specified parameters. + * This function creates a new test suite having the specified name and + * initialization/cleanup functions. The new suite is active for execution during + * test runs. The strName cannot be NULL (checked by assertion), but either or + * both function pointers can be. A pointer to the newly-created suite is returned, + * or NULL if there was an error allocating memory for the new suite. It is the + * responsibility of the caller to destroy the returned suite (use cleanup_suite() + * before freeing the returned pointer). + * + * @param strName Name for the new test suite (non-NULL). + * @param pInit Initialization function to call before running suite. + * @param pClean Cleanup function to call after running suite. + * @return A pointer to the newly-created suite (NULL if creation failed) + */ +static CU_pSuite create_suite(const char* strName, CU_InitializeFunc pInit, CU_CleanupFunc pClean) +{ + CU_pSuite pRetValue = (CU_pSuite)CU_MALLOC(sizeof(CU_Suite)); + + assert(NULL != strName); + + if (NULL != pRetValue) { + pRetValue->pName = (char *)CU_MALLOC(strlen(strName)+1); + if (NULL != pRetValue->pName) { + strcpy(pRetValue->pName, strName); + pRetValue->fActive = CU_TRUE; + pRetValue->pInitializeFunc = pInit; + pRetValue->pCleanupFunc = pClean; + pRetValue->pTest = NULL; + pRetValue->pNext = NULL; + pRetValue->pPrev = NULL; + pRetValue->uiNumberOfTests = 0; + } + else { + CU_FREE(pRetValue); + pRetValue = NULL; + } + } + + return pRetValue; +} + +/*------------------------------------------------------------------------*/ +/** + * Internal function to clean up the specified test suite. + * Each test case registered with pSuite will be freed. Allocated memory held + * by the suite (i.e. the name) will also be deallocated. Severe problems can + * occur if this function is called during a test run involving pSuite. + * + * @param pSuite CU_pSuite to clean up (non-NULL). + * @see cleanup_test_registry() + * @see cleanup_test() + */ +static void cleanup_suite(CU_pSuite pSuite) +{ + CU_pTest pCurTest = NULL; + CU_pTest pNextTest = NULL; + + assert(NULL != pSuite); + + pCurTest = pSuite->pTest; + while (NULL != pCurTest) { + pNextTest = pCurTest->pNext; + + cleanup_test(pCurTest); + + CU_FREE(pCurTest); + pCurTest = pNextTest; + } + if (NULL != pSuite->pName) { + CU_FREE(pSuite->pName); + } + + pSuite->pName = NULL; + pSuite->pTest = NULL; + pSuite->uiNumberOfTests = 0; +} + +/*------------------------------------------------------------------------*/ +/** + * Internal function to insert a suite into a registry. + * The suite name is assumed to be unique. Internally, the list of suites + * is a double-linked list, which this function manages. Insertion of NULL + * pSuites is not allowed (checked by assertion). Severe problems can occur + * if this function is called during a test run involving pRegistry. + * + * @param pRegistry CU_pTestRegistry to insert into (non-NULL). + * @param pSuite CU_pSuite to insert (non-NULL). + * @see insert_test() + */ +static void insert_suite(CU_pTestRegistry pRegistry, CU_pSuite pSuite) +{ + CU_pSuite pCurSuite = NULL; + + assert(NULL != pRegistry); + assert(NULL != pSuite); + + pCurSuite = pRegistry->pSuite; + + assert(pCurSuite != pSuite); + + pSuite->pNext = NULL; + pRegistry->uiNumberOfSuites++; + + /* if this is the 1st suite to be added... */ + if (NULL == pCurSuite) { + pRegistry->pSuite = pSuite; + pSuite->pPrev = NULL; + } + /* otherwise, add it to the end of the linked list... */ + else { + while (NULL != pCurSuite->pNext) { + pCurSuite = pCurSuite->pNext; + assert(pCurSuite != pSuite); + } + + pCurSuite->pNext = pSuite; + pSuite->pPrev = pCurSuite; + } +} + +/*------------------------------------------------------------------------*/ +/** + * Internal function to create a new test case having the specified parameters. + * This function creates a new test having the specified name and test function. + * The strName cannot be NULL (checked by assertion), but the function pointer + * may be. A pointer to the newly-created test is returned, or NULL if there + * was an error allocating memory for the new test. It is the responsibility + * of the caller to destroy the returned test (use cleanup_test() before freeing + * the returned pointer). + * + * @param strName Name for the new test. + * @param pTestFunc Test function to call when running this test. + * @return A pointer to the newly-created test (NULL if creation failed) + */ +static CU_pTest create_test(const char* strName, CU_TestFunc pTestFunc) +{ + CU_pTest pRetValue = (CU_pTest)CU_MALLOC(sizeof(CU_Test)); + + assert(NULL != strName); + + if (NULL != pRetValue) { + pRetValue->pName = (char *)CU_MALLOC(strlen(strName)+1); + if (NULL != pRetValue->pName) { + strcpy(pRetValue->pName, strName); + pRetValue->fActive = CU_TRUE; + pRetValue->pTestFunc = pTestFunc; + pRetValue->pJumpBuf = NULL; + pRetValue->pNext = NULL; + pRetValue->pPrev = NULL; + } + else { + CU_FREE(pRetValue); + pRetValue = NULL; + } + } + + return pRetValue; +} + +/*------------------------------------------------------------------------*/ +/** + * Internal function to clean up the specified test. + * All memory associated with the test will be freed. Severe problems can + * occur if this function is called during a test run involving pTest. + * + * @param pTest CU_pTest to clean up (non-NULL). + * @see cleanup_test_registry() + * @see cleanup_suite() + */ +static void cleanup_test(CU_pTest pTest) +{ + assert(NULL != pTest); + + if (NULL != pTest->pName) { + CU_FREE(pTest->pName); + } + + pTest->pName = NULL; +} + +/*------------------------------------------------------------------------*/ +/** + * Internal function to insert a test into a suite. + * The test name is assumed to be unique. Internally, the list of tests in + * a suite is a double-linked list, which this function manages. Neither + * pSuite nor pTest may be NULL (checked by assertion). Further, pTest must + * be an independent test (i.e. both pTest->pNext and pTest->pPrev == NULL), + * which is also checked by assertion. Severe problems can occur if this + * function is called during a test run involving pSuite. + * + * @param pSuite CU_pSuite to insert into (non-NULL). + * @param pTest CU_pTest to insert (non-NULL). + * @see insert_suite() + */ +static void insert_test(CU_pSuite pSuite, CU_pTest pTest) +{ + CU_pTest pCurTest = NULL; + + assert(NULL != pSuite); + assert(NULL != pTest); + assert(NULL == pTest->pNext); + assert(NULL == pTest->pPrev); + + pCurTest = pSuite->pTest; + + assert(pCurTest != pTest); + + pSuite->uiNumberOfTests++; + /* if this is the 1st suite to be added... */ + if (NULL == pCurTest) { + pSuite->pTest = pTest; + pTest->pPrev = NULL; + } + else { + while (NULL != pCurTest->pNext) { + pCurTest = pCurTest->pNext; + assert(pCurTest != pTest); + } + + pCurTest->pNext = pTest; + pTest->pPrev = pCurTest; + } +} + +/*------------------------------------------------------------------------*/ +/** + * Internal function to check whether a suite having a specified + * name already exists. + * + * @param pRegistry CU_pTestRegistry to check (non-NULL). + * @param szSuiteName Suite name to check (non-NULL). + * @return CU_TRUE if suite exists in the registry, CU_FALSE otherwise. + */ +static CU_BOOL suite_exists(CU_pTestRegistry pRegistry, const char* szSuiteName) +{ + CU_pSuite pSuite = NULL; + + assert(NULL != pRegistry); + assert(NULL != szSuiteName); + + pSuite = pRegistry->pSuite; + while (NULL != pSuite) { + if ((NULL != pSuite->pName) && (0 == CU_compare_strings(szSuiteName, pSuite->pName))) { + return CU_TRUE; + } + pSuite = pSuite->pNext; + } + + return CU_FALSE; +} + +/*------------------------------------------------------------------------*/ +/** + * Internal function to check whether a test having a specified + * name is already registered in a given suite. + * + * @param pSuite CU_pSuite to check (non-NULL). + * @param szTestName Test case name to check (non-NULL). + * @return CU_TRUE if test exists in the suite, CU_FALSE otherwise. + */ +static CU_BOOL test_exists(CU_pSuite pSuite, const char* szTestName) +{ + CU_pTest pTest = NULL; + + assert(NULL != pSuite); + assert(NULL != szTestName); + + pTest = pSuite->pTest; + while (NULL != pTest) { + if ((NULL != pTest->pName) && (0 == CU_compare_strings(szTestName, pTest->pName))) { + return CU_TRUE; + } + pTest = pTest->pNext; + } + + return CU_FALSE; +} + +/*================================================================= + * Public but primarily internal function definitions + *=================================================================*/ +CU_pTestRegistry CU_create_new_registry(void) +{ + CU_pTestRegistry pRegistry = (CU_pTestRegistry)CU_MALLOC(sizeof(CU_TestRegistry)); + if (NULL != pRegistry) { + pRegistry->pSuite = NULL; + pRegistry->uiNumberOfSuites = 0; + pRegistry->uiNumberOfTests = 0; + } + + return pRegistry; +} + +/*------------------------------------------------------------------------*/ +void CU_destroy_existing_registry(CU_pTestRegistry* ppRegistry) +{ + assert(NULL != ppRegistry); + + /* Note - CU_cleanup_registry counts on being able to pass NULL */ + + if (NULL != *ppRegistry) { + cleanup_test_registry(*ppRegistry); + } + CU_FREE(*ppRegistry); + *ppRegistry = NULL; +} + +/*------------------------------------------------------------------------*/ +CU_pSuite CU_get_suite_by_name(const char* szSuiteName, CU_pTestRegistry pRegistry) +{ + CU_pSuite pSuite = NULL; + CU_pSuite pCur = NULL; + + assert(NULL != pRegistry); + assert(NULL != szSuiteName); + + pCur = pRegistry->pSuite; + while (NULL != pCur) { + if ((NULL != pCur->pName) && (0 == CU_compare_strings(pCur->pName, szSuiteName))) { + pSuite = pCur; + break; + } + pCur = pCur->pNext; + } + + return pSuite; +} + +/*------------------------------------------------------------------------*/ +CU_pSuite CU_get_suite_by_index(unsigned int index, CU_pTestRegistry pRegistry) +{ + CU_pSuite result = NULL; + unsigned int i; + + assert(NULL != pRegistry); + + if ((index > 0) && (index <= f_pTestRegistry->uiNumberOfSuites)) { + result = f_pTestRegistry->pSuite; + for (i=1 ; ipNext; + } + } + + return result; +} + +/*------------------------------------------------------------------------*/ +CU_pTest CU_get_test_by_name(const char* szTestName, CU_pSuite pSuite) +{ + CU_pTest pTest = NULL; + CU_pTest pCur = NULL; + + assert(NULL != pSuite); + assert(NULL != szTestName); + + pCur = pSuite->pTest; + while (NULL != pCur) { + if ((NULL != pCur->pName) && (0 == CU_compare_strings(pCur->pName, szTestName))) { + pTest = pCur; + break; + } + pCur = pCur->pNext; + } + + return pTest; +} + +/*------------------------------------------------------------------------*/ +CU_pTest CU_get_test_by_index(unsigned int index, CU_pSuite pSuite) +{ + CU_pTest result = NULL; + unsigned int i; + + assert(NULL != pSuite); + + if ((index > 0) && (index <= pSuite->uiNumberOfTests)) { + result = pSuite->pTest; + for (i=1 ; ipNext; + } + } + + return result; +} +/** @} */ + +/*------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------*/ +#ifdef CUNIT_BUILD_TESTS +#include "test_cunit.h" + +static int sfunc1(void) +{ return 0; } + +static void test1(void) +{} + +static void test2(void) +{} + +/*--------------------------------------------------*/ +static void test_CU_initialize_registry(void) +{ + CU_pTestRegistry pReg = NULL; + unsigned int ndeallocs_before; + + /* initial state */ + TEST(NULL == CU_get_registry()); + TEST(CU_FALSE == CU_registry_initialized()); + + /* after normal initialization */ + TEST(CUE_SUCCESS == CU_initialize_registry()); + pReg = CU_get_registry(); + TEST_FATAL(NULL != pReg); + TEST(CU_TRUE == CU_registry_initialized()); + TEST(0 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + TEST(NULL == pReg->pSuite); + + /* after reinitialization */ + TEST(0 < test_cunit_get_n_memevents(pReg)); + ndeallocs_before = test_cunit_get_n_deallocations(pReg); + TEST(CUE_SUCCESS == CU_initialize_registry()); + TEST((ndeallocs_before + 1) == test_cunit_get_n_deallocations(pReg)); + pReg = CU_get_registry(); + TEST_FATAL(NULL != pReg); + TEST(0 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + TEST(NULL == pReg->pSuite); + + /* after cleanup */ + CU_cleanup_registry(); + TEST(NULL == CU_get_registry()); + TEST(CU_FALSE == CU_registry_initialized()); + + /* if malloc fails */ + test_cunit_deactivate_malloc(); + TEST(CUE_NOMEMORY == CU_initialize_registry()); + TEST(NULL == CU_get_registry()); + TEST(CU_FALSE == CU_registry_initialized()); + test_cunit_activate_malloc(); +} + +/*--------------------------------------------------*/ +static void test_CU_cleanup_registry(void) +{ + /* make sure calling with uninitialized registry does not crash */ + CU_cleanup_registry(); + CU_cleanup_registry(); + CU_cleanup_registry(); + CU_cleanup_registry(); + CU_cleanup_registry(); + + /* nothing more to do over test_CU_initialize_registry() */ +} + +/*--------------------------------------------------*/ +/* test CU_add_suite() + * CU_get_suite_by_name() + * CU_get_suite_by_index() + */ +static void test_CU_add_suite(void) +{ + CU_pSuite pSuite = NULL; + CU_pSuite pSuite2 = NULL; + CU_pSuite pSuite3 = NULL; + CU_pSuite pSuite4 = NULL; + CU_pTestRegistry pReg = NULL; + + CU_cleanup_registry(); /* make sure registry not initialized */ + + /* error condition - registry not initialized */ + pSuite = CU_add_suite("suite1", NULL, NULL); + TEST(CUE_NOREGISTRY == CU_get_error()); + TEST(NULL == pSuite); + + /* error condition - no name */ + CU_initialize_registry(); + pReg = CU_get_registry(); + + pSuite = CU_add_suite(NULL, NULL, NULL); + TEST(CUE_NO_SUITENAME == CU_get_error()); + TEST(NULL == pSuite); + TEST(0 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + + /* warning condition - duplicate name */ + CU_initialize_registry(); + pReg = CU_get_registry(); + + pSuite = CU_add_suite("suite1", NULL, NULL); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL != pSuite); + TEST(1 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + + pSuite2 = CU_add_suite("suite1", NULL, NULL); + TEST(CUE_DUP_SUITE == CU_get_error()); + TEST(NULL != pSuite2); + TEST(2 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + + TEST(!strcmp("suite1", pSuite->pName)); + TEST(pSuite->fActive == CU_TRUE); /* suite active on creation */ + TEST(pSuite->pTest == NULL); /* no tests added yet */ + TEST(pSuite->uiNumberOfTests == 0); /* no tests added yet */ + TEST(pSuite->pInitializeFunc == NULL); /* no init function */ + TEST(pSuite->pCleanupFunc == NULL); /* no cleanup function */ + TEST(pSuite->pNext == pSuite2); /* now have another suite */ + + TEST(!strcmp("suite1", pSuite2->pName)); + TEST(pSuite2->fActive == CU_TRUE); /* suite active on creation */ + TEST(pSuite2->pTest == NULL); /* no tests added yet */ + TEST(pSuite2->uiNumberOfTests == 0); /* no tests added yet */ + TEST(pSuite2->pInitializeFunc == NULL); /* no init function */ + TEST(pSuite2->pCleanupFunc == NULL); /* no cleanup function */ + TEST(pSuite2->pNext == NULL); /* end of the list */ + + /* error condition - memory allocation failure */ + CU_initialize_registry(); + pReg = CU_get_registry(); + + test_cunit_deactivate_malloc(); + pSuite = CU_add_suite("suite1", NULL, NULL); + TEST(CUE_NOMEMORY == CU_get_error()); + TEST(NULL == pSuite); + TEST(0 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + test_cunit_activate_malloc(); + + /* normal creation & cleanup */ + CU_initialize_registry(); + pReg = CU_get_registry(); + + TEST(CU_get_suite_by_index(0, pReg) == NULL); + TEST(CU_get_suite_by_index(1, pReg) == NULL); + + pSuite = CU_add_suite("suite1", NULL, NULL); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL != pSuite); + TEST(1 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + TEST(CU_get_suite_by_name("suite1", pReg) == pSuite); + TEST(CU_get_suite_by_index(0, pReg) == NULL); + TEST(CU_get_suite_by_index(1, pReg) == pSuite); + TEST(CU_get_suite_by_index(2, pReg) == NULL); + TEST(pReg->pSuite == pSuite); + + TEST(!strcmp("suite1", pSuite->pName)); + TEST(pSuite->fActive == CU_TRUE); /* suite active on creation */ + TEST(pSuite->pTest == NULL); /* no tests added yet */ + TEST(pSuite->uiNumberOfTests == 0); /* no tests added yet */ + TEST(pSuite->pInitializeFunc == NULL); /* no init function */ + TEST(pSuite->pCleanupFunc == NULL); /* no cleanup function */ + TEST(pSuite->pNext == NULL); /* no more suites added yet */ + + pSuite2 = CU_add_suite("suite2", sfunc1, NULL); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL != pSuite2); + TEST(2 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + TEST(CU_get_suite_by_name("suite2", pReg) == pSuite2); + TEST(CU_get_suite_by_index(0, pReg) == NULL); + TEST(CU_get_suite_by_index(1, pReg) == pSuite); + TEST(CU_get_suite_by_index(2, pReg) == pSuite2); + TEST(CU_get_suite_by_index(3, pReg) == NULL); + + pSuite3 = CU_add_suite("suite3", NULL, sfunc1); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL != pSuite3); + TEST(3 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + TEST(CU_get_suite_by_name("suite3", pReg) == pSuite3); + TEST(CU_get_suite_by_index(0, pReg) == NULL); + TEST(CU_get_suite_by_index(1, pReg) == pSuite); + TEST(CU_get_suite_by_index(2, pReg) == pSuite2); + TEST(CU_get_suite_by_index(3, pReg) == pSuite3); + TEST(CU_get_suite_by_index(4, pReg) == NULL); + + pSuite4 = CU_add_suite("suite4", sfunc1, sfunc1); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL != pSuite4); + TEST(4 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + TEST(CU_get_suite_by_name("suite4", pReg) == pSuite4); + TEST(CU_get_suite_by_index(0, pReg) == NULL); + TEST(CU_get_suite_by_index(1, pReg) == pSuite); + TEST(CU_get_suite_by_index(2, pReg) == pSuite2); + TEST(CU_get_suite_by_index(3, pReg) == pSuite3); + TEST(CU_get_suite_by_index(4, pReg) == pSuite4); + TEST(CU_get_suite_by_index(5, pReg) == NULL); + + /* test registry suite structures */ + TEST(pReg->pSuite == pSuite); + + TEST(!strcmp("suite1", pSuite->pName)); + TEST(pSuite->fActive == CU_TRUE); /* suite active on creation */ + TEST(pSuite->pTest == NULL); /* no tests added yet */ + TEST(pSuite->uiNumberOfTests == 0); /* no tests added yet */ + TEST(pSuite->pInitializeFunc == NULL); /* no init function */ + TEST(pSuite->pCleanupFunc == NULL); /* no cleanup function */ + TEST(pSuite->pNext == pSuite2); /* now have another suite */ + + TEST(!strcmp("suite2", pSuite2->pName)); + TEST(pSuite2->fActive == CU_TRUE); /* suite active on creation */ + TEST(pSuite2->pTest == NULL); /* no tests added yet */ + TEST(pSuite2->uiNumberOfTests == 0); /* no tests added yet */ + TEST(pSuite2->pInitializeFunc == sfunc1); /* no init function */ + TEST(pSuite2->pCleanupFunc == NULL); /* no cleanup function */ + TEST(pSuite2->pNext == pSuite3); /* next suite in list */ + + TEST(!strcmp("suite3", pSuite3->pName)); + TEST(pSuite3->fActive == CU_TRUE); /* suite active on creation */ + TEST(pSuite3->pTest == NULL); /* no tests added yet */ + TEST(pSuite3->uiNumberOfTests == 0); /* no tests added yet */ + TEST(pSuite3->pInitializeFunc == NULL); /* no init function */ + TEST(pSuite3->pCleanupFunc == sfunc1); /* no cleanup function */ + TEST(pSuite3->pNext == pSuite4); /* next suite in list */ + + TEST(!strcmp("suite4", pSuite4->pName)); + TEST(pSuite4->fActive == CU_TRUE); /* suite active on creation */ + TEST(pSuite4->pTest == NULL); /* no tests added yet */ + TEST(pSuite4->uiNumberOfTests == 0); /* no tests added yet */ + TEST(pSuite4->pInitializeFunc == sfunc1); /* no init function */ + TEST(pSuite4->pCleanupFunc == sfunc1); /* no cleanup function */ + TEST(pSuite4->pNext == NULL); /* end of suite list */ + + TEST(0 != test_cunit_get_n_memevents(pSuite)); + TEST(0 != test_cunit_get_n_memevents(pSuite2)); + TEST(0 != test_cunit_get_n_memevents(pSuite3)); + TEST(0 != test_cunit_get_n_memevents(pSuite4)); + + TEST(test_cunit_get_n_allocations(pSuite) != test_cunit_get_n_deallocations(pSuite)); + TEST(test_cunit_get_n_allocations(pSuite2) != test_cunit_get_n_deallocations(pSuite2)); + TEST(test_cunit_get_n_allocations(pSuite3) != test_cunit_get_n_deallocations(pSuite3)); + TEST(test_cunit_get_n_allocations(pSuite4) != test_cunit_get_n_deallocations(pSuite4)); + + /* clean up everything and confirm deallocation */ + CU_cleanup_registry(); + + TEST(test_cunit_get_n_allocations(pSuite) == test_cunit_get_n_deallocations(pSuite)); + TEST(test_cunit_get_n_allocations(pSuite2) == test_cunit_get_n_deallocations(pSuite2)); + TEST(test_cunit_get_n_allocations(pSuite3) == test_cunit_get_n_deallocations(pSuite3)); + TEST(test_cunit_get_n_allocations(pSuite4) == test_cunit_get_n_deallocations(pSuite4)); +} + +/*--------------------------------------------------*/ +/* test CU_set_suite_active() + * CU_set_suite_name() + * CU_set_suite_initfunc() + * CU_set_suite_cleanupfunc() + */ +static void test_CU_set_suite_attributes(void) +{ + CU_pSuite pSuite1 = NULL; + CU_pSuite pSuite2 = NULL; + + /* initialize system */ + CU_initialize_registry(); + + pSuite1 = CU_add_suite("suite1", NULL, NULL); + TEST_FATAL(NULL != pSuite1); + TEST_FATAL(NULL != CU_add_test(pSuite1, "test1", test1)); + TEST_FATAL(NULL != CU_add_test(pSuite1, "test2", test1)); + + pSuite2 = CU_add_suite("suite2", sfunc1, NULL); /* add another suite */ + TEST_FATAL(NULL != pSuite2); + TEST_FATAL(NULL != CU_add_test(pSuite2, "test1", test1)); + TEST_FATAL(NULL != CU_add_test(pSuite2, "test2", test1)); + + /* test CU_set_suite_active() */ + TEST(CUE_NOSUITE == CU_set_suite_active(NULL, CU_FALSE)); /* error - NULL suite */ + + TEST(pSuite2->fActive == CU_TRUE); /* suites active on creation */ + TEST(pSuite1->fActive == CU_TRUE); + + TEST(CUE_SUCCESS == CU_set_suite_active(pSuite1, CU_TRUE)); + TEST(CUE_SUCCESS == CU_set_suite_active(pSuite2, CU_FALSE)); + TEST(pSuite1->fActive == CU_TRUE); + TEST(pSuite2->fActive == CU_FALSE); + + TEST(CUE_SUCCESS == CU_set_suite_active(pSuite1, CU_FALSE)); + TEST(CUE_SUCCESS == CU_set_suite_active(pSuite2, CU_FALSE)); + TEST(pSuite1->fActive == CU_FALSE); + TEST(pSuite2->fActive == CU_FALSE); + + TEST(CUE_SUCCESS == CU_set_suite_active(pSuite1, CU_FALSE)); + TEST(CUE_SUCCESS == CU_set_suite_active(pSuite2, CU_TRUE)); + TEST(pSuite1->fActive == CU_FALSE); + TEST(pSuite2->fActive == CU_TRUE); + + /* test CU_set_suite_name() */ + TEST(CUE_NOSUITE == CU_set_suite_name(NULL, "null suite")); /* error - NULL suite */ + TEST(CUE_NO_SUITENAME == CU_set_suite_name(pSuite1, NULL)); /* error - NULL name */ + + TEST(!strcmp(pSuite1->pName, "suite1")); + TEST(!strcmp(pSuite2->pName, "suite2")); + TEST(CUE_SUCCESS == CU_set_suite_name(pSuite1, "This is my new name.")); + TEST(!strcmp(pSuite1->pName, "This is my new name.")); + TEST(!strcmp(pSuite2->pName, "suite2")); + + TEST(CUE_SUCCESS == CU_set_suite_name(pSuite2, "Never mind.")); + TEST(!strcmp(pSuite1->pName, "This is my new name.")); + TEST(!strcmp(pSuite2->pName, "Never mind.")); + + TEST(CUE_SUCCESS == CU_set_suite_name(pSuite1, "suite1")); + TEST(CUE_SUCCESS == CU_set_suite_name(pSuite2, "suite2")); + TEST(!strcmp(pSuite1->pName, "suite1")); + TEST(!strcmp(pSuite2->pName, "suite2")); + + /* test CU_set_suite_initfunc() */ + TEST(CUE_NOSUITE == CU_set_suite_initfunc(NULL, &sfunc1)); /* error - NULL suite */ + + TEST(pSuite1->pInitializeFunc == NULL); + TEST(pSuite2->pInitializeFunc == &sfunc1); + TEST(CUE_SUCCESS == CU_set_suite_initfunc(pSuite1, &sfunc1)); + TEST(pSuite1->pInitializeFunc == &sfunc1); + TEST(pSuite2->pInitializeFunc == &sfunc1); + + TEST(CUE_SUCCESS == CU_set_suite_initfunc(pSuite2, NULL)); + TEST(pSuite1->pInitializeFunc == &sfunc1); + TEST(pSuite2->pInitializeFunc == NULL); + + /* test CU_set_suite_cleanupfunc() */ + TEST(CUE_NOSUITE == CU_set_suite_cleanupfunc(NULL, &sfunc1)); + + TEST(pSuite1->pCleanupFunc == NULL); + TEST(pSuite2->pCleanupFunc == NULL); + TEST(CUE_SUCCESS == CU_set_suite_cleanupfunc(pSuite1, &sfunc1)); + TEST(pSuite1->pCleanupFunc == &sfunc1); + TEST(pSuite2->pCleanupFunc == NULL); + + TEST(CUE_SUCCESS == CU_set_suite_cleanupfunc(pSuite2, &sfunc1)); + TEST(pSuite1->pCleanupFunc == &sfunc1); + TEST(pSuite2->pCleanupFunc == &sfunc1); + + /* clean up */ + CU_cleanup_registry(); +} + +static void test_succeed(void) { CU_TEST(CU_TRUE); } +static void test_fail(void) { CU_TEST(CU_FALSE); } +static int suite_succeed(void) { return 0; } +static int suite_fail(void) { return 1; } + +/*--------------------------------------------------*/ +/* test CU_get_suite() + * CU_get_suite_at_pos() + * CU_get_suite_pos() + * CU_get_suite_pos_by_name() + */ +static void test_get_suite_functions(void) +{ + CU_pSuite pSuite1 = NULL; + CU_pSuite pSuite2 = NULL; + CU_pSuite pSuite3 = NULL; + CU_pSuite pSuite4 = NULL; + CU_pSuite pSuite5 = NULL; + CU_pTest pTest1 = NULL; + CU_pTest pTest2 = NULL; + CU_pTest pTest3 = NULL; + CU_pTest pTest4 = NULL; + CU_pTest pTest5 = NULL; + CU_pTest pTest6 = NULL; + CU_pTest pTest7 = NULL; + CU_pTest pTest8 = NULL; + CU_pTest pTest9 = NULL; + CU_pTest pTest10 = NULL; + + /* error condition - registry not initialized */ + CU_cleanup_registry(); + + CU_set_error(CUE_SUCCESS); + TEST(NULL == CU_get_suite("suite1")); + TEST(CUE_NOREGISTRY == CU_get_error()); + + CU_set_error(CUE_SUCCESS); + TEST(NULL == CU_get_suite_at_pos(0)); + TEST(CUE_NOREGISTRY == CU_get_error()); + + CU_set_error(CUE_SUCCESS); + TEST(0 == CU_get_suite_pos(pSuite1)); + TEST(CUE_NOREGISTRY == CU_get_error()); + + CU_set_error(CUE_SUCCESS); + TEST(0 == CU_get_suite_pos_by_name("suite1")); + TEST(CUE_NOREGISTRY == CU_get_error()); + + /* register some suites and tests */ + CU_initialize_registry(); + pSuite1 = CU_add_suite("suite1", NULL, NULL); + pTest1 = CU_add_test(pSuite1, "test1", test_succeed); + pTest2 = CU_add_test(pSuite1, "test2", test_fail); + pTest3 = CU_add_test(pSuite1, "test1", test_succeed); /* duplicate test name */ + pTest4 = CU_add_test(pSuite1, "test4", test_fail); + pTest5 = CU_add_test(pSuite1, "test1", test_succeed); /* duplicate test name */ + pSuite2 = CU_add_suite("suite2", suite_fail, NULL); + pTest6 = CU_add_test(pSuite2, "test6", test_succeed); + pTest7 = CU_add_test(pSuite2, "test7", test_succeed); + pSuite3 = CU_add_suite("suite1", NULL, NULL); /* duplicate suite name */ + pTest8 = CU_add_test(pSuite3, "test8", test_fail); + pTest9 = CU_add_test(pSuite3, "test9", test_succeed); + pSuite4 = CU_add_suite("suite4", NULL, suite_fail); + pTest10 = CU_add_test(pSuite4, "test10", test_succeed); + + /* error condition - invalid parameters */ + + CU_set_error(CUE_SUCCESS); + TEST(NULL == CU_get_suite(NULL)); + TEST(CUE_NO_SUITENAME == CU_get_error()); + + CU_set_error(CUE_SUCCESS); + TEST(0 == CU_get_suite_pos(NULL)); + TEST(CUE_NOSUITE == CU_get_error()); + + CU_set_error(CUE_SUCCESS); + TEST(0 == CU_get_suite_pos_by_name(NULL)); + TEST(CUE_NO_SUITENAME == CU_get_error()); + + /* normal operation - CU_get_suite() */ + + TEST(NULL == CU_get_suite("")); /* invalid names */ + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL == CU_get_suite("bad name")); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL == CU_get_suite("suite3")); + TEST(CUE_SUCCESS == CU_get_error()); + + TEST(pSuite1 == CU_get_suite("suite1")); /* valid names */ + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pSuite2 == CU_get_suite("suite2")); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pSuite4 == CU_get_suite("suite4")); + TEST(CUE_SUCCESS == CU_get_error()); + + /* normal operation - CU_get_suite_at_pos() */ + + TEST(NULL == CU_get_suite_at_pos(0)); /* invalid positions */ + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL == CU_get_suite_at_pos(5)); + TEST(CUE_SUCCESS == CU_get_error()); + + TEST(pSuite1 == CU_get_suite_at_pos(1)); /* valid positions */ + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pSuite2 == CU_get_suite_at_pos(2)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pSuite3 == CU_get_suite_at_pos(3)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pSuite4 == CU_get_suite_at_pos(4)); + TEST(CUE_SUCCESS == CU_get_error()); + + /* normal operation - CU_get_suite_pos() */ + + pSuite5 = (CU_pSuite)malloc(sizeof(CU_Suite)); + TEST_FATAL(NULL != pSuite5); + + TEST(0 == CU_get_suite_pos(pSuite5)); /* invalid suite */ + TEST(CUE_SUCCESS == CU_get_error()); + + TEST(1 == CU_get_suite_pos(pSuite1)); /* valid suites */ + TEST(CUE_SUCCESS == CU_get_error()); + TEST(2 == CU_get_suite_pos(pSuite2)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(3 == CU_get_suite_pos(pSuite3)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(4 == CU_get_suite_pos(pSuite4)); + TEST(CUE_SUCCESS == CU_get_error()); + + free(pSuite5); + + /* normal operation - CU_get_suite_pos_by_name() */ + + TEST(0 == CU_get_suite_pos_by_name("")); /* invalid names */ + TEST(CUE_SUCCESS == CU_get_error()); + TEST(0 == CU_get_suite_pos_by_name("suite3")); + TEST(CUE_SUCCESS == CU_get_error()); + + TEST(1 == CU_get_suite_pos_by_name("suite1")); /* valid suites */ + TEST(CUE_SUCCESS == CU_get_error()); + TEST(2 == CU_get_suite_pos_by_name("suite2")); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(4 == CU_get_suite_pos_by_name("suite4")); + TEST(CUE_SUCCESS == CU_get_error()); + + /* clean up */ + CU_cleanup_registry(); +} + +/*--------------------------------------------------*/ +/* test CU_add_test() + * CU_get_test_by_name() + * CU_get_test_by_index() + */ +static void test_CU_add_test(void) +{ + CU_pSuite pSuite1 = NULL; + CU_pSuite pSuite2 = NULL; + CU_pTest pTest1 = NULL; + CU_pTest pTest2 = NULL; + CU_pTest pTest3 = NULL; + CU_pTest pTest4 = NULL; + CU_pTestRegistry pReg = NULL; + + CU_cleanup_registry(); + + /* error condition - registry not initialized */ + pTest1 = CU_add_test(pSuite1, "test1", test1); + TEST(CUE_NOREGISTRY == CU_get_error()); + TEST(NULL == pTest1); + + CU_initialize_registry(); + pReg = CU_get_registry(); + + /* error condition - no suite */ + pTest1 = CU_add_test(pSuite1, "test1", test1); + TEST(CUE_NOSUITE == CU_get_error()); + TEST(NULL == pTest1); + + /* error condition - no name */ + pSuite1 = CU_add_suite("suite1", NULL, NULL); + TEST(CUE_SUCCESS == CU_get_error()); + pTest1 = CU_add_test(pSuite1, NULL, test1); + TEST(CUE_NO_TESTNAME == CU_get_error()); + TEST(NULL == pTest1); + TEST(1 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + TEST(0 == pSuite1->uiNumberOfTests); + + /* error condition - no test function */ + pTest1 = CU_add_test(pSuite1, "test1", NULL); + TEST(CUE_NOTEST == CU_get_error()); + TEST(NULL == pTest1); + TEST(1 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + TEST(0 == pSuite1->uiNumberOfTests); + + /* warning condition - duplicate name */ + CU_initialize_registry(); + pReg = CU_get_registry(); + + pSuite1 = CU_add_suite("suite1", NULL, NULL); + TEST(CUE_SUCCESS == CU_get_error()); + pTest1 = CU_add_test(pSuite1, "test1", test1); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL != pTest1); + TEST(1 == pReg->uiNumberOfSuites); + TEST(1 == pReg->uiNumberOfTests); + TEST(1 == pSuite1->uiNumberOfTests); + TEST(CU_get_test_by_index(0, pSuite1) == NULL); + TEST(CU_get_test_by_index(1, pSuite1) == pTest1); + TEST(CU_get_test_by_index(2, pSuite1) == NULL); + + pTest2 = CU_add_test(pSuite1, "test1", test1); + TEST(CUE_DUP_TEST == CU_get_error()); + TEST(NULL != pTest2); + TEST(1 == pReg->uiNumberOfSuites); + TEST(2 == pReg->uiNumberOfTests); + TEST(2 == pSuite1->uiNumberOfTests); + + TEST(!strcmp("test1", pTest1->pName)); + TEST(pTest1->fActive == CU_TRUE); + TEST(pTest1->pNext == pTest2); + TEST(pTest1->pJumpBuf == NULL); + TEST(pTest1->pTestFunc == test1); + TEST(CU_get_test_by_name("test1", pSuite1) == pTest1); + TEST(CU_get_test_by_index(0, pSuite1) == NULL); + TEST(CU_get_test_by_index(1, pSuite1) == pTest1); + TEST(CU_get_test_by_index(2, pSuite1) == pTest2); + TEST(CU_get_test_by_index(3, pSuite1) == NULL); + + TEST(!strcmp("test1", pTest2->pName)); + TEST(pTest2->fActive == CU_TRUE); + TEST(pTest2->pNext == NULL); + TEST(pTest2->pJumpBuf == NULL); + TEST(pTest2->pTestFunc == test1); + TEST(CU_get_test_by_name("test1", pSuite1) == pTest1); + + /* error condition - memory allocation failure */ + CU_initialize_registry(); + pReg = CU_get_registry(); + + pSuite1 = CU_add_suite("suite1", NULL, NULL); + TEST(CUE_SUCCESS == CU_get_error()); + test_cunit_deactivate_malloc(); + pTest1 = CU_add_test(pSuite1, "test1", test1); + test_cunit_activate_malloc(); + TEST(CUE_NOMEMORY == CU_get_error()); + TEST(NULL == pTest1); + TEST(1 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + TEST(0 == pSuite1->uiNumberOfTests); + + /* normal creation & cleanup */ + CU_initialize_registry(); + pReg = CU_get_registry(); + + pSuite1 = CU_add_suite("suite1", NULL, NULL); + TEST(CUE_SUCCESS == CU_get_error()); + pSuite2 = CU_add_suite("suite2", sfunc1, sfunc1); + TEST(CUE_SUCCESS == CU_get_error()); + + TEST(CU_get_test_by_index(0, pSuite1) == NULL); + TEST(CU_get_test_by_index(1, pSuite1) == NULL); + + pTest1 = CU_add_test(pSuite1, "test1", test1); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL != pTest1); + TEST(2 == pReg->uiNumberOfSuites); + TEST(1 == pReg->uiNumberOfTests); + TEST(1 == pSuite1->uiNumberOfTests); + TEST(0 == pSuite2->uiNumberOfTests); + TEST(pSuite1->pTest == pTest1); + TEST(pSuite2->pTest == NULL); + TEST(CU_get_test_by_index(0, pSuite1) == NULL); + TEST(CU_get_test_by_index(1, pSuite1) == pTest1); + TEST(CU_get_test_by_index(2, pSuite1) == NULL); + + pTest2 = CU_add_test(pSuite2, "test2", test1); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL != pTest2); + TEST(2 == pReg->uiNumberOfSuites); + TEST(2 == pReg->uiNumberOfTests); + TEST(1 == pSuite1->uiNumberOfTests); + TEST(1 == pSuite2->uiNumberOfTests); + TEST(pSuite1->pTest == pTest1); + TEST(pSuite2->pTest == pTest2); + TEST(CU_get_test_by_index(0, pSuite2) == NULL); + TEST(CU_get_test_by_index(1, pSuite2) == pTest2); + TEST(CU_get_test_by_index(2, pSuite2) == NULL); + + pTest3 = CU_add_test(pSuite1, "test3", test1); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL != pTest3); + TEST(2 == pReg->uiNumberOfSuites); + TEST(3 == pReg->uiNumberOfTests); + TEST(2 == pSuite1->uiNumberOfTests); + TEST(1 == pSuite2->uiNumberOfTests); + TEST(pSuite1->pTest == pTest1); + TEST(pSuite2->pTest == pTest2); + TEST(CU_get_test_by_index(0, pSuite1) == NULL); + TEST(CU_get_test_by_index(1, pSuite1) == pTest1); + TEST(CU_get_test_by_index(2, pSuite1) == pTest3); + TEST(CU_get_test_by_index(3, pSuite1) == NULL); + + pTest4 = CU_add_test(pSuite1, "test4", test1); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL != pTest4); + TEST(2 == pReg->uiNumberOfSuites); + TEST(4 == pReg->uiNumberOfTests); + TEST(3 == pSuite1->uiNumberOfTests); + TEST(1 == pSuite2->uiNumberOfTests); + TEST(pSuite1->pTest == pTest1); + TEST(pSuite2->pTest == pTest2); + TEST(CU_get_test_by_index(0, pSuite1) == NULL); + TEST(CU_get_test_by_index(1, pSuite1) == pTest1); + TEST(CU_get_test_by_index(2, pSuite1) == pTest3); + TEST(CU_get_test_by_index(3, pSuite1) == pTest4); + TEST(CU_get_test_by_index(4, pSuite1) == NULL); + + TEST(!strcmp("test1", pTest1->pName)); + TEST(pTest1->pNext == pTest3); + TEST(pTest1->pJumpBuf == NULL); + TEST(pTest1->pTestFunc == test1); + TEST(CU_get_test_by_name("test1", pSuite1) == pTest1); + TEST(CU_get_test_by_name("test1", pSuite2) == NULL); + + TEST(!strcmp("test2", pTest2->pName)); + TEST(pTest2->pNext == NULL); + TEST(pTest2->pJumpBuf == NULL); + TEST(pTest2->pTestFunc == test1); + TEST(CU_get_test_by_name("test2", pSuite1) == NULL); + TEST(CU_get_test_by_name("test2", pSuite2) == pTest2); + + TEST(!strcmp("test3", pTest3->pName)); + TEST(pTest3->pNext == pTest4); + TEST(pTest3->pJumpBuf == NULL); + TEST(pTest3->pTestFunc == test1); + TEST(CU_get_test_by_name("test3", pSuite1) == pTest3); + TEST(CU_get_test_by_name("test3", pSuite2) == NULL); + + TEST(!strcmp("test4", pTest4->pName)); + TEST(pTest4->pNext == NULL); + TEST(pTest4->pJumpBuf == NULL); + TEST(pTest4->pTestFunc == test1); + TEST(CU_get_test_by_name("test4", pSuite1) == pTest4); + TEST(CU_get_test_by_name("test4", pSuite2) == NULL); + + TEST(0 != test_cunit_get_n_memevents(pSuite1)); + TEST(0 != test_cunit_get_n_memevents(pSuite2)); + TEST(0 != test_cunit_get_n_memevents(pTest1)); + TEST(0 != test_cunit_get_n_memevents(pTest2)); + TEST(0 != test_cunit_get_n_memevents(pTest3)); + TEST(0 != test_cunit_get_n_memevents(pTest4)); + + TEST(test_cunit_get_n_allocations(pSuite1) != test_cunit_get_n_deallocations(pSuite1)); + TEST(test_cunit_get_n_allocations(pSuite2) != test_cunit_get_n_deallocations(pSuite2)); + TEST(test_cunit_get_n_allocations(pTest1) != test_cunit_get_n_deallocations(pTest1)); + TEST(test_cunit_get_n_allocations(pTest2) != test_cunit_get_n_deallocations(pTest2)); + TEST(test_cunit_get_n_allocations(pTest3) != test_cunit_get_n_deallocations(pTest3)); + TEST(test_cunit_get_n_allocations(pTest4) != test_cunit_get_n_deallocations(pTest4)); + + CU_cleanup_registry(); + + TEST(test_cunit_get_n_allocations(pSuite1) == test_cunit_get_n_deallocations(pSuite1)); + TEST(test_cunit_get_n_allocations(pSuite2) == test_cunit_get_n_deallocations(pSuite2)); + TEST(test_cunit_get_n_allocations(pTest1) == test_cunit_get_n_deallocations(pTest1)); + TEST(test_cunit_get_n_allocations(pTest2) == test_cunit_get_n_deallocations(pTest2)); + TEST(test_cunit_get_n_allocations(pTest3) == test_cunit_get_n_deallocations(pTest3)); + TEST(test_cunit_get_n_allocations(pTest4) == test_cunit_get_n_deallocations(pTest4)); +} + +/*--------------------------------------------------*/ +/* test CU_set_test_active() + * CU_set_test_name() + * CU_set_test_func() + */ +static void test_CU_set_test_attributes(void) +{ + CU_pSuite pSuite1 = NULL; + CU_pSuite pSuite2 = NULL; + CU_pTest pTest1 = NULL; + CU_pTest pTest2 = NULL; + CU_pTest pTest3 = NULL; + CU_pTest pTest4 = NULL; + + /* initialize system */ + CU_initialize_registry(); + + pSuite1 = CU_add_suite("suite1", NULL, NULL); + TEST_FATAL(NULL != pSuite1); + pTest1 = CU_add_test(pSuite1, "test1", test2); + TEST_FATAL(NULL != pTest1); + pTest2 = CU_add_test(pSuite1, "test2", test1); + TEST_FATAL(NULL != pTest2); + + pSuite2 = CU_add_suite("suite2", sfunc1, NULL); /* add another suite */ + TEST_FATAL(NULL != pSuite2); + pTest3 = CU_add_test(pSuite2, "test3", test2); + TEST_FATAL(NULL != pTest3); + pTest4 = CU_add_test(pSuite2, "test4", test1); + TEST_FATAL(NULL != pTest4); + + /* test CU_set_test_active() */ + TEST(CUE_NOTEST == CU_set_test_active(NULL, CU_FALSE)); /* error - NULL test */ + + TEST(CU_TRUE == pTest1->fActive); /* tests active on creation */ + TEST(CU_TRUE == pTest2->fActive); + TEST(CU_TRUE == pTest3->fActive); + TEST(CU_TRUE == pTest4->fActive); + + TEST(CUE_SUCCESS == CU_set_test_active(pTest1, CU_TRUE)); + TEST(CUE_SUCCESS == CU_set_test_active(pTest2, CU_TRUE)); + TEST(CUE_SUCCESS == CU_set_test_active(pTest3, CU_FALSE)); + TEST(CUE_SUCCESS == CU_set_test_active(pTest4, CU_FALSE)); + TEST(CU_TRUE == pTest1->fActive); + TEST(CU_TRUE == pTest2->fActive); + TEST(CU_FALSE == pTest3->fActive); + TEST(CU_FALSE == pTest4->fActive); + + TEST(CUE_SUCCESS == CU_set_test_active(pTest1, CU_FALSE)); + TEST(CUE_SUCCESS == CU_set_test_active(pTest2, CU_TRUE)); + TEST(CUE_SUCCESS == CU_set_test_active(pTest3, CU_TRUE)); + TEST(CUE_SUCCESS == CU_set_test_active(pTest4, CU_FALSE)); + TEST(CU_FALSE == pTest1->fActive); + TEST(CU_TRUE == pTest2->fActive); + TEST(CU_TRUE == pTest3->fActive); + TEST(CU_FALSE == pTest4->fActive); + + TEST(CUE_SUCCESS == CU_set_test_active(pTest1, CU_FALSE)); + TEST(CUE_SUCCESS == CU_set_test_active(pTest2, CU_FALSE)); + TEST(CUE_SUCCESS == CU_set_test_active(pTest3, CU_FALSE)); + TEST(CUE_SUCCESS == CU_set_test_active(pTest4, CU_FALSE)); + TEST(CU_FALSE == pTest1->fActive); + TEST(CU_FALSE == pTest2->fActive); + TEST(CU_FALSE == pTest3->fActive); + TEST(CU_FALSE == pTest4->fActive); + + TEST(CUE_SUCCESS == CU_set_test_active(pTest1, CU_TRUE)); + TEST(CUE_SUCCESS == CU_set_test_active(pTest2, CU_TRUE)); + TEST(CUE_SUCCESS == CU_set_test_active(pTest3, CU_TRUE)); + TEST(CUE_SUCCESS == CU_set_test_active(pTest4, CU_TRUE)); + TEST(CU_TRUE == pTest1->fActive); + TEST(CU_TRUE == pTest2->fActive); + TEST(CU_TRUE == pTest3->fActive); + TEST(CU_TRUE == pTest4->fActive); + + /* test CU_set_test_name() */ + TEST(CUE_NOTEST == CU_set_test_name(NULL, "null test")); /* error - NULL test */ + TEST(CUE_NO_TESTNAME == CU_set_test_name(pTest1, NULL)); /* error - NULL name */ + + TEST(!strcmp("test1", pTest1->pName)); + TEST(!strcmp("test2", pTest2->pName)); + TEST(!strcmp("test3", pTest3->pName)); + TEST(!strcmp("test4", pTest4->pName)); + + TEST(CUE_SUCCESS == CU_set_test_name(pTest1, "Aren't I a pretty girl?")); + TEST(CUE_SUCCESS == CU_set_test_name(pTest2, "Polly want a cracker.")); + TEST(CUE_SUCCESS == CU_set_test_name(pTest3, "@This is utter nonsense@")); + TEST(CUE_SUCCESS == CU_set_test_name(pTest4, "Yep!")); + + TEST(!strcmp("Aren't I a pretty girl?", pTest1->pName)); + TEST(!strcmp("Polly want a cracker.", pTest2->pName)); + TEST(!strcmp("@This is utter nonsense@", pTest3->pName)); + TEST(!strcmp("Yep!", pTest4->pName)); + + TEST(CUE_SUCCESS == CU_set_test_name(pTest1, "test1")); + TEST(CUE_SUCCESS == CU_set_test_name(pTest2, "test2")); + TEST(CUE_SUCCESS == CU_set_test_name(pTest3, "test3")); + TEST(CUE_SUCCESS == CU_set_test_name(pTest4, "test4")); + + TEST(!strcmp("test1", pTest1->pName)); + TEST(!strcmp("test2", pTest2->pName)); + TEST(!strcmp("test3", pTest3->pName)); + TEST(!strcmp("test4", pTest4->pName)); + + /* test CU_set_test_func() */ + TEST(CUE_NOTEST == CU_set_test_func(NULL, &test1)); /* error - NULL test */ + TEST(CUE_NOTEST == CU_set_test_func(pTest1, NULL)); /* error - NULL test function */ + + TEST(&test2 == pTest1->pTestFunc); + TEST(&test1 == pTest2->pTestFunc); + TEST(&test2 == pTest3->pTestFunc); + TEST(&test1 == pTest4->pTestFunc); + + TEST(CUE_SUCCESS == CU_set_test_func(pTest1, &test1)); + TEST(CUE_SUCCESS == CU_set_test_func(pTest2, &test2)); + TEST(CUE_SUCCESS == CU_set_test_func(pTest3, &test1)); + TEST(CUE_SUCCESS == CU_set_test_func(pTest4, &test2)); + + TEST(&test1 == pTest1->pTestFunc); + TEST(&test2 == pTest2->pTestFunc); + TEST(&test1 == pTest3->pTestFunc); + TEST(&test2 == pTest4->pTestFunc); + + TEST(CUE_SUCCESS == CU_set_test_func(pTest1, &test2)); + TEST(CUE_SUCCESS == CU_set_test_func(pTest2, &test1)); + TEST(CUE_SUCCESS == CU_set_test_func(pTest3, &test2)); + TEST(CUE_SUCCESS == CU_set_test_func(pTest4, &test1)); + + /* clean up */ + CU_cleanup_registry(); +} + +/*--------------------------------------------------*/ +/* test CU_get_test() + * CU_get_test_at_pos() + * CU_get_test_pos() + * CU_get_test_pos_by_name() + */ +static void test_get_test_functions(void) +{ + CU_pSuite pSuite1 = NULL; + CU_pSuite pSuite2 = NULL; + CU_pSuite pSuite3 = NULL; + CU_pSuite pSuite4 = NULL; + CU_pTest pTest1 = NULL; + CU_pTest pTest2 = NULL; + CU_pTest pTest3 = NULL; + CU_pTest pTest4 = NULL; + CU_pTest pTest5 = NULL; + CU_pTest pTest6 = NULL; + CU_pTest pTest7 = NULL; + CU_pTest pTest8 = NULL; + CU_pTest pTest9 = NULL; + CU_pTest pTest10 = NULL; + + /* error condition - registry not initialized */ + CU_cleanup_registry(); + + CU_set_error(CUE_SUCCESS); + TEST(NULL == CU_get_test(pSuite1, "test1")); + TEST(CUE_NOREGISTRY == CU_get_error()); + + CU_set_error(CUE_SUCCESS); + TEST(NULL == CU_get_test_at_pos(pSuite1, 0)); + TEST(CUE_NOREGISTRY == CU_get_error()); + + CU_set_error(CUE_SUCCESS); + TEST(0 == CU_get_test_pos(pSuite1, pTest1)); + TEST(CUE_NOREGISTRY == CU_get_error()); + + CU_set_error(CUE_SUCCESS); + TEST(0 == CU_get_test_pos_by_name(pSuite1, "test1")); + TEST(CUE_NOREGISTRY == CU_get_error()); + + /* register some suites and tests */ + CU_initialize_registry(); + pSuite1 = CU_add_suite("suite1", NULL, NULL); + pTest1 = CU_add_test(pSuite1, "test1", test_succeed); + pTest2 = CU_add_test(pSuite1, "test2", test_fail); + pTest3 = CU_add_test(pSuite1, "test1", test_succeed); /* duplicate test name */ + pTest4 = CU_add_test(pSuite1, "test4", test_fail); + pTest5 = CU_add_test(pSuite1, "test1", test_succeed); /* duplicate test name */ + pSuite2 = CU_add_suite("suite2", suite_fail, NULL); + pTest6 = CU_add_test(pSuite2, "test6", test_succeed); + pTest7 = CU_add_test(pSuite2, "test7", test_succeed); + pSuite3 = CU_add_suite("suite1", NULL, NULL); /* duplicate suite name */ + pTest8 = CU_add_test(pSuite3, "test8", test_fail); + pTest9 = CU_add_test(pSuite3, "test9", test_succeed); + pSuite4 = CU_add_suite("suite4", NULL, suite_fail); + pTest10 = CU_add_test(pSuite4, "test10", test_succeed); + + /* error condition - invalid parameters */ + + CU_set_error(CUE_SUCCESS); + TEST(NULL == CU_get_test(NULL, "test1")); /* suite NULL */ + TEST(CUE_NOSUITE == CU_get_error()); + + CU_set_error(CUE_SUCCESS); + TEST(NULL == CU_get_test(pSuite1, NULL)); /* name NULL */ + TEST(CUE_NO_SUITENAME == CU_get_error()); + + CU_set_error(CUE_SUCCESS); + TEST(0 == CU_get_test_at_pos(NULL, 1)); /* suite NULL */ + TEST(CUE_NOSUITE == CU_get_error()); + + CU_set_error(CUE_SUCCESS); + TEST(0 == CU_get_test_pos(NULL, pTest1)); /* suite NULL */ + TEST(CUE_NOSUITE == CU_get_error()); + + CU_set_error(CUE_SUCCESS); + TEST(0 == CU_get_test_pos(pSuite1, NULL)); /* test NULL */ + TEST(CUE_NOTEST == CU_get_error()); + + CU_set_error(CUE_SUCCESS); + TEST(0 == CU_get_test_pos_by_name(NULL, "test1")); /* suite NULL */ + TEST(CUE_NOSUITE == CU_get_error()); + + CU_set_error(CUE_SUCCESS); + TEST(0 == CU_get_test_pos_by_name(pSuite1, NULL)); /* name NULL */ + TEST(CUE_NO_TESTNAME == CU_get_error()); + + /* normal operation - CU_get_test() */ + + TEST(NULL == CU_get_test(pSuite1, "")); /* invalid names */ + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL == CU_get_test(pSuite2, "bad name")); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL == CU_get_test(pSuite1, "test3")); + TEST(CUE_SUCCESS == CU_get_error()); + + TEST(pTest1 == CU_get_test(pSuite1, "test1")); /* valid names */ + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pTest6 == CU_get_test(pSuite2, "test6")); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pTest8 == CU_get_test(pSuite3, "test8")); + TEST(CUE_SUCCESS == CU_get_error()); + + /* normal operation - CU_get_test_at_pos() */ + + TEST(NULL == CU_get_test_at_pos(pSuite1, 0)); /* invalid positions */ + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL == CU_get_test_at_pos(pSuite1, 6)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(NULL == CU_get_test_at_pos(pSuite4, 2)); + TEST(CUE_SUCCESS == CU_get_error()); + + TEST(pTest1 == CU_get_test_at_pos(pSuite1, 1)); /* valid positions */ + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pTest2 == CU_get_test_at_pos(pSuite1, 2)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pTest3 == CU_get_test_at_pos(pSuite1, 3)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pTest4 == CU_get_test_at_pos(pSuite1, 4)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pTest5 == CU_get_test_at_pos(pSuite1, 5)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pTest6 == CU_get_test_at_pos(pSuite2, 1)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pTest7 == CU_get_test_at_pos(pSuite2, 2)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pTest8 == CU_get_test_at_pos(pSuite3, 1)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pTest9 == CU_get_test_at_pos(pSuite3, 2)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(pTest10 == CU_get_test_at_pos(pSuite4, 1)); + TEST(CUE_SUCCESS == CU_get_error()); + + /* normal operation - CU_get_test_pos() */ + + TEST(0 == CU_get_test_pos(pSuite1, pTest6)); /* invalid tests */ + TEST(CUE_SUCCESS == CU_get_error()); + TEST(0 == CU_get_test_pos(pSuite4, pTest6)); + TEST(CUE_SUCCESS == CU_get_error()); + + TEST(1 == CU_get_test_pos(pSuite1, pTest1)); /* valid tests */ + TEST(CUE_SUCCESS == CU_get_error()); + TEST(2 == CU_get_test_pos(pSuite1, pTest2)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(3 == CU_get_test_pos(pSuite1, pTest3)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(4 == CU_get_test_pos(pSuite1, pTest4)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(5 == CU_get_test_pos(pSuite1, pTest5)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(1 == CU_get_test_pos(pSuite2, pTest6)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(2 == CU_get_test_pos(pSuite2, pTest7)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(1 == CU_get_test_pos(pSuite3, pTest8)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(2 == CU_get_test_pos(pSuite3, pTest9)); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(1 == CU_get_test_pos(pSuite4, pTest10)); + TEST(CUE_SUCCESS == CU_get_error()); + + /* normal operation - CU_get_test_pos_by_name() */ + + TEST(0 == CU_get_test_pos_by_name(pSuite1, "")); /* invalid names */ + TEST(CUE_SUCCESS == CU_get_error()); + TEST(0 == CU_get_test_pos_by_name(pSuite1, "test9")); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(0 == CU_get_test_pos_by_name(pSuite2, "test1")); + TEST(CUE_SUCCESS == CU_get_error()); + + TEST(1 == CU_get_test_pos_by_name(pSuite1, "test1")); /* valid names */ + TEST(CUE_SUCCESS == CU_get_error()); + TEST(2 == CU_get_test_pos_by_name(pSuite1, "test2")); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(4 == CU_get_test_pos_by_name(pSuite1, "test4")); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(1 == CU_get_test_pos_by_name(pSuite2, "test6")); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(2 == CU_get_test_pos_by_name(pSuite2, "test7")); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(1 == CU_get_test_pos_by_name(pSuite3, "test8")); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(2 == CU_get_test_pos_by_name(pSuite3, "test9")); + TEST(CUE_SUCCESS == CU_get_error()); + TEST(1 == CU_get_test_pos_by_name(pSuite4, "test10")); + TEST(CUE_SUCCESS == CU_get_error()); + + /* clean up */ + CU_cleanup_registry(); +} + +/*--------------------------------------------------*/ +static void test_CU_get_registry(void) +{ + CU_cleanup_registry(); + TEST(NULL == CU_get_registry()); + + CU_initialize_registry(); + TEST(NULL != CU_get_registry()); + TEST(f_pTestRegistry == CU_get_registry()); + + CU_cleanup_registry(); +} + +/*--------------------------------------------------*/ +static void test_CU_set_registry(void) +{ + CU_pTestRegistry pReg1 = NULL; + CU_pTestRegistry pReg2 = NULL; + CU_pSuite pSuite1 = NULL; + CU_pSuite pSuite2 = NULL; + + CU_initialize_registry(); + pSuite1 = CU_add_suite("suite1", NULL, NULL); + pSuite2 = CU_add_suite("suite2", NULL, NULL); + + CU_add_test(pSuite1, "test1", test1); + CU_add_test(pSuite1, "test2", test1); + CU_add_test(pSuite2, "test1", test1); + CU_add_test(pSuite2, "test2", test1); + + pReg1 = CU_get_registry(); + + TEST(pReg1->pSuite == pSuite1); + TEST(pReg1->uiNumberOfSuites == 2); + TEST(pReg1->uiNumberOfTests == 4); + TEST(0 < test_cunit_get_n_memevents(pReg1)); + TEST(test_cunit_get_n_allocations(pReg1) != test_cunit_get_n_deallocations(pReg1)); + + CU_set_registry(NULL); + + TEST(test_cunit_get_n_allocations(pReg1) != test_cunit_get_n_deallocations(pReg1)); + + CU_cleanup_registry(); + + TEST(test_cunit_get_n_allocations(pReg1) != test_cunit_get_n_deallocations(pReg1)); + + pReg2 = CU_create_new_registry(); + CU_set_registry(pReg2); + + TEST(pReg1->pSuite == pSuite1); + TEST(pReg1->uiNumberOfSuites == 2); + TEST(pReg1->uiNumberOfTests == 4); + TEST(test_cunit_get_n_allocations(pReg1) != test_cunit_get_n_deallocations(pReg1)); + + TEST(CU_get_registry()->pSuite == NULL); + TEST(CU_get_registry()->uiNumberOfSuites == 0); + TEST(CU_get_registry()->uiNumberOfTests == 0); + TEST(0 < test_cunit_get_n_memevents(pReg2)); + TEST(test_cunit_get_n_allocations(pReg2) != test_cunit_get_n_deallocations(pReg2)); + + CU_cleanup_registry(); + + TEST(pReg1->pSuite == pSuite1); + TEST(pReg1->uiNumberOfSuites == 2); + TEST(pReg1->uiNumberOfTests == 4); + TEST(test_cunit_get_n_allocations(pReg1) != test_cunit_get_n_deallocations(pReg1)); + TEST(test_cunit_get_n_allocations(pReg2) == test_cunit_get_n_deallocations(pReg2)); + + CU_set_registry(pReg1); + CU_cleanup_registry(); + TEST(test_cunit_get_n_allocations(pReg1) == test_cunit_get_n_deallocations(pReg1)); +} + +/*--------------------------------------------------*/ +/* test CU_create_new_registry() + * CU_destroy_existing_registry() + */ +static void test_CU_create_new_registry(void) +{ + CU_pTestRegistry pReg = NULL; + CU_pTestRegistry pRegOld = NULL; + + CU_cleanup_registry(); + pReg = CU_create_new_registry(); + + TEST(NULL != pReg); + TEST(0 < test_cunit_get_n_memevents(pReg)); + TEST(test_cunit_get_n_allocations(pReg) != test_cunit_get_n_deallocations(pReg)); + + TEST(pReg->pSuite == NULL); + TEST(pReg->uiNumberOfSuites == 0); + TEST(pReg->uiNumberOfTests == 0); + + CU_cleanup_registry(); + TEST(test_cunit_get_n_allocations(pReg) != test_cunit_get_n_deallocations(pReg)); + + pRegOld = pReg; + CU_destroy_existing_registry(&pReg); + TEST(test_cunit_get_n_allocations(pRegOld) == test_cunit_get_n_deallocations(pRegOld)); + TEST(NULL == pReg); +} + +/*--------------------------------------------------*/ +static void test_cleanup_test_registry(void) +{ + CU_pSuite pSuite1 = NULL; + CU_pSuite pSuite2 = NULL; + CU_pTest pTest1 = NULL; + CU_pTest pTest2 = NULL; + CU_pTest pTest3 = NULL; + CU_pTest pTest4 = NULL; + CU_pTestRegistry pReg = CU_create_new_registry(); + + TEST_FATAL(NULL != pReg); + TEST(0 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + + /* create tests to register */ + pTest1 = create_test("test1", test1); + pTest2 = create_test("test2", NULL); + pTest3 = create_test("test3", test1); + pTest4 = create_test("", NULL); + + /* create suites to hold tests */ + pSuite1 = create_suite("suite1", NULL, NULL); + pSuite2 = create_suite("suite2", sfunc1, sfunc1); + insert_suite(pReg, pSuite1); + insert_suite(pReg, pSuite2); + + insert_test(pSuite1, pTest1); + insert_test(pSuite1, pTest2); + insert_test(pSuite1, pTest3); + insert_test(pSuite2, pTest4); + + TEST(2 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); /* not managed in primitive functions */ + TEST(3 == pSuite1->uiNumberOfTests); + TEST(1 == pSuite2->uiNumberOfTests); + TEST(pSuite1->pTest == pTest1); + TEST(pSuite2->pTest == pTest4); + TEST(pTest1->pNext == pTest2); + TEST(pTest1->pPrev == NULL); + TEST(pTest2->pNext == pTest3); + TEST(pTest2->pPrev == pTest1); + TEST(pTest3->pNext == NULL); + TEST(pTest3->pPrev == pTest2); + TEST(pTest4->pNext == NULL); + TEST(pTest4->pPrev == NULL); + + TEST(0 != test_cunit_get_n_memevents(pReg)); + TEST(0 != test_cunit_get_n_memevents(pSuite1)); + TEST(0 != test_cunit_get_n_memevents(pSuite2)); + TEST(0 != test_cunit_get_n_memevents(pTest1)); + TEST(0 != test_cunit_get_n_memevents(pTest2)); + TEST(0 != test_cunit_get_n_memevents(pTest3)); + TEST(0 != test_cunit_get_n_memevents(pTest4)); + + TEST(test_cunit_get_n_allocations(pReg) != test_cunit_get_n_deallocations(pReg)); + TEST(test_cunit_get_n_allocations(pSuite1) != test_cunit_get_n_deallocations(pSuite1)); + TEST(test_cunit_get_n_allocations(pSuite2) != test_cunit_get_n_deallocations(pSuite2)); + TEST(test_cunit_get_n_allocations(pTest1) != test_cunit_get_n_deallocations(pTest1)); + TEST(test_cunit_get_n_allocations(pTest2) != test_cunit_get_n_deallocations(pTest2)); + TEST(test_cunit_get_n_allocations(pTest3) != test_cunit_get_n_deallocations(pTest3)); + TEST(test_cunit_get_n_allocations(pTest4) != test_cunit_get_n_deallocations(pTest4)); + + cleanup_test_registry(pReg); + CU_FREE(pReg); + + TEST(test_cunit_get_n_allocations(pReg) == test_cunit_get_n_deallocations(pReg)); + TEST(test_cunit_get_n_allocations(pSuite1) == test_cunit_get_n_deallocations(pSuite1)); + TEST(test_cunit_get_n_allocations(pSuite2) == test_cunit_get_n_deallocations(pSuite2)); + TEST(test_cunit_get_n_allocations(pTest1) == test_cunit_get_n_deallocations(pTest1)); + TEST(test_cunit_get_n_allocations(pTest2) == test_cunit_get_n_deallocations(pTest2)); + TEST(test_cunit_get_n_allocations(pTest3) == test_cunit_get_n_deallocations(pTest3)); + TEST(test_cunit_get_n_allocations(pTest4) == test_cunit_get_n_deallocations(pTest4)); +} + +/*--------------------------------------------------*/ +/* test create_suite() + * cleanup_suite() + */ +static void test_create_suite(void) +{ + CU_pSuite pSuite1 = NULL; + CU_pSuite pSuite2 = NULL; + CU_pSuite pSuite3 = NULL; + CU_pSuite pSuite4 = NULL; + + /* error condition - memory allocation failure */ + test_cunit_deactivate_malloc(); + pSuite1 = create_suite("suite1", NULL, NULL); + TEST(NULL == pSuite1); + test_cunit_activate_malloc(); + + /* normal creation & cleanup */ + pSuite1 = create_suite("suite1", NULL, NULL); + TEST(NULL != pSuite1); + TEST(!strcmp("suite1", pSuite1->pName)); + TEST(pSuite1->pTest == NULL); /* no tests added yet */ + TEST(pSuite1->uiNumberOfTests == 0); /* no tests added yet */ + TEST(pSuite1->pInitializeFunc == NULL); /* no init function */ + TEST(pSuite1->pCleanupFunc == NULL); /* no cleanup function */ + TEST(pSuite1->pNext == NULL); /* no more suites added yet */ + + pSuite2 = create_suite("suite2", sfunc1, NULL); + TEST(NULL != pSuite2); + TEST(!strcmp("suite2", pSuite2->pName)); + TEST(pSuite2->pTest == NULL); /* no tests added yet */ + TEST(pSuite2->uiNumberOfTests == 0); /* no tests added yet */ + TEST(pSuite2->pInitializeFunc == sfunc1); /* init function */ + TEST(pSuite2->pCleanupFunc == NULL); /* no cleanup function */ + TEST(pSuite2->pNext == NULL); /* no more suites added yet */ + + pSuite3 = create_suite("suite3", NULL, sfunc1); + TEST(NULL != pSuite3); + TEST(!strcmp("suite3", pSuite3->pName)); + TEST(pSuite3->pTest == NULL); /* no tests added yet */ + TEST(pSuite3->uiNumberOfTests == 0); /* no tests added yet */ + TEST(pSuite3->pInitializeFunc == NULL); /* no init function */ + TEST(pSuite3->pCleanupFunc == sfunc1); /* cleanup function */ + TEST(pSuite3->pNext == NULL); /* no more suites added yet */ + + pSuite4 = create_suite("suite4", sfunc1, sfunc1); + TEST(NULL != pSuite4); + TEST(!strcmp("suite4", pSuite4->pName)); + TEST(pSuite4->pTest == NULL); /* no tests added yet */ + TEST(pSuite4->uiNumberOfTests == 0); /* no tests added yet */ + TEST(pSuite4->pInitializeFunc == sfunc1); /* no init function */ + TEST(pSuite4->pCleanupFunc == sfunc1); /* cleanup function */ + TEST(pSuite4->pNext == NULL); /* no more suites added yet */ + + TEST(0 != test_cunit_get_n_memevents(pSuite1)); + TEST(test_cunit_get_n_allocations(pSuite1) != test_cunit_get_n_deallocations(pSuite1)); + cleanup_suite(pSuite1); + CU_FREE(pSuite1); + TEST(test_cunit_get_n_allocations(pSuite1) == test_cunit_get_n_deallocations(pSuite1)); + + TEST(0 != test_cunit_get_n_memevents(pSuite2)); + TEST(test_cunit_get_n_allocations(pSuite2) != test_cunit_get_n_deallocations(pSuite2)); + cleanup_suite(pSuite2); + CU_FREE(pSuite2); + TEST(test_cunit_get_n_allocations(pSuite2) == test_cunit_get_n_deallocations(pSuite2)); + + TEST(0 != test_cunit_get_n_memevents(pSuite3)); + TEST(test_cunit_get_n_allocations(pSuite3) != test_cunit_get_n_deallocations(pSuite3)); + cleanup_suite(pSuite3); + CU_FREE(pSuite3); + TEST(test_cunit_get_n_allocations(pSuite3) == test_cunit_get_n_deallocations(pSuite3)); + + TEST(0 != test_cunit_get_n_memevents(pSuite4)); + TEST(test_cunit_get_n_allocations(pSuite4) != test_cunit_get_n_deallocations(pSuite4)); + cleanup_suite(pSuite4); + CU_FREE(pSuite4); + TEST(test_cunit_get_n_allocations(pSuite4) == test_cunit_get_n_deallocations(pSuite4)); +} + +/*--------------------------------------------------*/ +/* test insert_suite() + * suite_exists() + */ +static void test_insert_suite(void) +{ + CU_pSuite pSuite1 = NULL; + CU_pSuite pSuite2 = NULL; + CU_pSuite pSuite3 = NULL; + CU_pSuite pSuite4 = NULL; + CU_pTestRegistry pReg = CU_create_new_registry(); + + TEST_FATAL(NULL != pReg); + TEST(0 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + TEST(NULL == pReg->pSuite); + TEST(CU_FALSE == suite_exists(pReg, "suite1")); + TEST(CU_FALSE == suite_exists(pReg, "suite2")); + TEST(CU_FALSE == suite_exists(pReg, "suite3")); + TEST(CU_FALSE == suite_exists(pReg, "suite4")); + TEST(CU_FALSE == suite_exists(pReg, "suite5")); + TEST(CU_FALSE == suite_exists(pReg, "")); + + /* normal creation & cleanup */ + pSuite1 = create_suite("suite1", NULL, NULL); + insert_suite(pReg, pSuite1); + TEST(1 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + TEST(pReg->pSuite == pSuite1); + TEST(pSuite1->pNext == NULL); + TEST(CU_TRUE == suite_exists(pReg, "suite1")); + TEST(CU_FALSE == suite_exists(pReg, "suite2")); + TEST(CU_FALSE == suite_exists(pReg, "suite3")); + TEST(CU_FALSE == suite_exists(pReg, "suite4")); + TEST(CU_FALSE == suite_exists(pReg, "suite5")); + TEST(CU_FALSE == suite_exists(pReg, "")); + + pSuite2 = create_suite("suite2", sfunc1, NULL); + insert_suite(pReg, pSuite2); + TEST(2 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + TEST(pReg->pSuite == pSuite1); + TEST(pSuite1->pNext == pSuite2); + TEST(pSuite2->pNext == NULL); + TEST(CU_TRUE == suite_exists(pReg, "suite1")); + TEST(CU_TRUE == suite_exists(pReg, "suite2")); + TEST(CU_FALSE == suite_exists(pReg, "suite3")); + TEST(CU_FALSE == suite_exists(pReg, "suite4")); + TEST(CU_FALSE == suite_exists(pReg, "suite5")); + TEST(CU_FALSE == suite_exists(pReg, "")); + + pSuite3 = create_suite("suite3", NULL, sfunc1); + insert_suite(pReg, pSuite3); + TEST(3 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + TEST(pReg->pSuite == pSuite1); + TEST(pSuite1->pNext == pSuite2); + TEST(pSuite2->pNext == pSuite3); + TEST(pSuite3->pNext == NULL); + TEST(CU_TRUE == suite_exists(pReg, "suite1")); + TEST(CU_TRUE == suite_exists(pReg, "suite2")); + TEST(CU_TRUE == suite_exists(pReg, "suite3")); + TEST(CU_FALSE == suite_exists(pReg, "suite4")); + TEST(CU_FALSE == suite_exists(pReg, "suite5")); + TEST(CU_FALSE == suite_exists(pReg, "")); + + pSuite4 = create_suite("suite4", sfunc1, sfunc1); + insert_suite(pReg, pSuite4); + TEST(4 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + TEST(pReg->pSuite == pSuite1); + TEST(pSuite1->pNext == pSuite2); + TEST(pSuite2->pNext == pSuite3); + TEST(pSuite3->pNext == pSuite4); + TEST(pSuite4->pNext == NULL); + TEST(CU_TRUE == suite_exists(pReg, "suite1")); + TEST(CU_TRUE == suite_exists(pReg, "suite2")); + TEST(CU_TRUE == suite_exists(pReg, "suite3")); + TEST(CU_TRUE == suite_exists(pReg, "suite4")); + TEST(CU_FALSE == suite_exists(pReg, "suite5")); + TEST(CU_FALSE == suite_exists(pReg, "")); + + TEST(0 != test_cunit_get_n_memevents(pReg)); + TEST(0 != test_cunit_get_n_memevents(pSuite1)); + TEST(0 != test_cunit_get_n_memevents(pSuite2)); + TEST(0 != test_cunit_get_n_memevents(pSuite3)); + TEST(0 != test_cunit_get_n_memevents(pSuite4)); + + TEST(test_cunit_get_n_allocations(pReg) != test_cunit_get_n_deallocations(pReg)); + TEST(test_cunit_get_n_allocations(pSuite1) != test_cunit_get_n_deallocations(pSuite1)); + TEST(test_cunit_get_n_allocations(pSuite2) != test_cunit_get_n_deallocations(pSuite2)); + TEST(test_cunit_get_n_allocations(pSuite3) != test_cunit_get_n_deallocations(pSuite3)); + TEST(test_cunit_get_n_allocations(pSuite4) != test_cunit_get_n_deallocations(pSuite4)); + + cleanup_test_registry(pReg); + TEST(CU_FALSE == suite_exists(pReg, "suite1")); + TEST(CU_FALSE == suite_exists(pReg, "suite2")); + TEST(CU_FALSE == suite_exists(pReg, "suite3")); + TEST(CU_FALSE == suite_exists(pReg, "suite4")); + TEST(CU_FALSE == suite_exists(pReg, "suite5")); + TEST(CU_FALSE == suite_exists(pReg, "")); + CU_FREE(pReg); + + TEST(test_cunit_get_n_allocations(pReg) == test_cunit_get_n_deallocations(pReg)); + TEST(test_cunit_get_n_allocations(pSuite1) == test_cunit_get_n_deallocations(pSuite1)); + TEST(test_cunit_get_n_allocations(pSuite2) == test_cunit_get_n_deallocations(pSuite2)); + TEST(test_cunit_get_n_allocations(pSuite3) == test_cunit_get_n_deallocations(pSuite3)); + TEST(test_cunit_get_n_allocations(pSuite4) == test_cunit_get_n_deallocations(pSuite4)); +} + +/*--------------------------------------------------*/ +static void test_create_test(void) +{ + CU_pTest pTest1 = NULL; + CU_pTest pTest2 = NULL; + + /* error condition - memory allocation failure */ + test_cunit_deactivate_malloc(); + pTest1 = create_test("test1", test1); + test_cunit_activate_malloc(); + TEST(NULL == pTest1); + + /* normal creation & cleanup */ + pTest1 = create_test("test1", test1); + TEST(NULL != pTest1); + TEST(pTest1->pTestFunc == test1); + TEST(!strcmp("test1", pTest1->pName)); + TEST(pTest1->pNext == NULL); + TEST(pTest1->pPrev == NULL); + TEST(pTest1->pJumpBuf == NULL); + + pTest2= create_test("test2", NULL); + TEST(NULL != pTest2); + TEST(pTest2->pTestFunc == NULL); + TEST(!strcmp("test2", pTest2->pName)); + TEST(pTest2->pNext == NULL); + TEST(pTest2->pPrev == NULL); + TEST(pTest2->pJumpBuf == NULL); + + TEST(0 != test_cunit_get_n_memevents(pTest1)); + TEST(0 != test_cunit_get_n_memevents(pTest2)); + + TEST(test_cunit_get_n_allocations(pTest1) != test_cunit_get_n_deallocations(pTest1)); + TEST(test_cunit_get_n_allocations(pTest2) != test_cunit_get_n_deallocations(pTest2)); + + cleanup_test(pTest1); + CU_FREE(pTest1); + cleanup_test(pTest2); + CU_FREE(pTest2); + + TEST(test_cunit_get_n_allocations(pTest1) == test_cunit_get_n_deallocations(pTest1)); + TEST(test_cunit_get_n_allocations(pTest2) == test_cunit_get_n_deallocations(pTest2)); +} + +/*--------------------------------------------------*/ +/* test insert_test() + * test_exists() + */ +static void test_insert_test(void) +{ + CU_pSuite pSuite1 = NULL; + CU_pSuite pSuite2 = NULL; + CU_pTest pTest1 = NULL; + CU_pTest pTest2 = NULL; + CU_pTest pTest3 = NULL; + CU_pTest pTest4 = NULL; + + /* create tests to register */ + pTest1 = create_test("test1", test1); + pTest2 = create_test("test2", NULL); + pTest3 = create_test("test3", test1); + pTest4 = create_test("", NULL); + + /* create suites to hold tests */ + pSuite1 = create_suite("suite1", NULL, NULL); + pSuite2 = create_suite("suite2", sfunc1, sfunc1); + + TEST(CU_FALSE == test_exists(pSuite1, "test1")); + TEST(CU_FALSE == test_exists(pSuite1, "test2")); + TEST(CU_FALSE == test_exists(pSuite1, "test3")); + TEST(CU_FALSE == test_exists(pSuite1, "test4")); + TEST(CU_FALSE == test_exists(pSuite1, "")); + TEST(CU_FALSE == test_exists(pSuite2, "test1")); + TEST(CU_FALSE == test_exists(pSuite2, "test2")); + TEST(CU_FALSE == test_exists(pSuite2, "test3")); + TEST(CU_FALSE == test_exists(pSuite2, "test4")); + TEST(CU_FALSE == test_exists(pSuite2, "")); + + insert_test(pSuite1, pTest1); + insert_test(pSuite1, pTest2); + insert_test(pSuite1, pTest3); + insert_test(pSuite2, pTest4); + + TEST(CU_TRUE == test_exists(pSuite1, "test1")); + TEST(CU_TRUE == test_exists(pSuite1, "test2")); + TEST(CU_TRUE == test_exists(pSuite1, "test3")); + TEST(CU_FALSE == test_exists(pSuite1, "test4")); + TEST(CU_FALSE == test_exists(pSuite1, "")); + TEST(CU_FALSE == test_exists(pSuite2, "test1")); + TEST(CU_FALSE == test_exists(pSuite2, "test2")); + TEST(CU_FALSE == test_exists(pSuite2, "test3")); + TEST(CU_FALSE == test_exists(pSuite2, "test4")); + TEST(CU_TRUE == test_exists(pSuite2, "")); + + TEST(3 == pSuite1->uiNumberOfTests); + TEST(1 == pSuite2->uiNumberOfTests); + TEST(pSuite1->pTest == pTest1); + TEST(pSuite2->pTest == pTest4); + TEST(pTest1->pNext == pTest2); + TEST(pTest1->pPrev == NULL); + TEST(pTest2->pNext == pTest3); + TEST(pTest2->pPrev == pTest1); + TEST(pTest3->pNext == NULL); + TEST(pTest3->pPrev == pTest2); + TEST(pTest4->pNext == NULL); + TEST(pTest4->pPrev == NULL); + + TEST(0 != test_cunit_get_n_memevents(pSuite1)); + TEST(0 != test_cunit_get_n_memevents(pSuite2)); + TEST(0 != test_cunit_get_n_memevents(pTest1)); + TEST(0 != test_cunit_get_n_memevents(pTest2)); + TEST(0 != test_cunit_get_n_memevents(pTest3)); + TEST(0 != test_cunit_get_n_memevents(pTest4)); + + TEST(test_cunit_get_n_allocations(pSuite1) != test_cunit_get_n_deallocations(pSuite1)); + TEST(test_cunit_get_n_allocations(pSuite2) != test_cunit_get_n_deallocations(pSuite2)); + TEST(test_cunit_get_n_allocations(pTest1) != test_cunit_get_n_deallocations(pTest1)); + TEST(test_cunit_get_n_allocations(pTest2) != test_cunit_get_n_deallocations(pTest2)); + TEST(test_cunit_get_n_allocations(pTest3) != test_cunit_get_n_deallocations(pTest3)); + TEST(test_cunit_get_n_allocations(pTest4) != test_cunit_get_n_deallocations(pTest4)); + + cleanup_suite(pSuite1); + + TEST(CU_FALSE == test_exists(pSuite1, "test1")); + TEST(CU_FALSE == test_exists(pSuite1, "test2")); + TEST(CU_FALSE == test_exists(pSuite1, "test3")); + TEST(CU_FALSE == test_exists(pSuite1, "test4")); + TEST(CU_FALSE == test_exists(pSuite1, "")); + TEST(CU_FALSE == test_exists(pSuite2, "test1")); + TEST(CU_FALSE == test_exists(pSuite2, "test2")); + TEST(CU_FALSE == test_exists(pSuite2, "test3")); + TEST(CU_FALSE == test_exists(pSuite2, "test4")); + TEST(CU_TRUE == test_exists(pSuite2, "")); + + cleanup_suite(pSuite2); + + TEST(CU_FALSE == test_exists(pSuite1, "test1")); + TEST(CU_FALSE == test_exists(pSuite1, "test2")); + TEST(CU_FALSE == test_exists(pSuite1, "test3")); + TEST(CU_FALSE == test_exists(pSuite1, "test4")); + TEST(CU_FALSE == test_exists(pSuite1, "")); + TEST(CU_FALSE == test_exists(pSuite2, "test1")); + TEST(CU_FALSE == test_exists(pSuite2, "test2")); + TEST(CU_FALSE == test_exists(pSuite2, "test3")); + TEST(CU_FALSE == test_exists(pSuite2, "test4")); + TEST(CU_FALSE == test_exists(pSuite2, "")); + + CU_FREE(pSuite1); + CU_FREE(pSuite2); + + TEST(test_cunit_get_n_allocations(pSuite1) == test_cunit_get_n_deallocations(pSuite1)); + TEST(test_cunit_get_n_allocations(pSuite2) == test_cunit_get_n_deallocations(pSuite2)); + TEST(test_cunit_get_n_allocations(pTest1) == test_cunit_get_n_deallocations(pTest1)); + TEST(test_cunit_get_n_allocations(pTest2) == test_cunit_get_n_deallocations(pTest2)); + TEST(test_cunit_get_n_allocations(pTest3) == test_cunit_get_n_deallocations(pTest3)); + TEST(test_cunit_get_n_allocations(pTest4) == test_cunit_get_n_deallocations(pTest4)); +} + +/*--------------------------------------------------*/ +static void test_cleanup_test(void) +{ + char* pName; + CU_pTest pTest1 = create_test("test1", NULL); + + TEST_FATAL(NULL != pTest1); + + pName = pTest1->pName; + TEST(0 != test_cunit_get_n_memevents(pTest1)); + TEST(0 != test_cunit_get_n_memevents(pName)); + + TEST(test_cunit_get_n_allocations(pTest1) != test_cunit_get_n_deallocations(pTest1)); + TEST(test_cunit_get_n_allocations(pName) != test_cunit_get_n_deallocations(pName)); + + cleanup_test(pTest1); + CU_FREE(pTest1); + + TEST(test_cunit_get_n_allocations(pTest1) == test_cunit_get_n_deallocations(pTest1)); + TEST(test_cunit_get_n_allocations(pName) == test_cunit_get_n_deallocations(pName)); +} + +/*--------------------------------------------------*/ +static void group_A_case_1(void) +{ + CU_ASSERT_TRUE(1); +} + +static void group_A_case_2(void) +{ + CU_ASSERT_TRUE(2); +} + +static void group_B_case_1(void) +{ + CU_ASSERT_FALSE(1); +} + +static void group_B_case_2(void) +{ + CU_ASSERT_FALSE(2); +} + +static CU_TestInfo group_A_test_cases[] = { + { "1", group_A_case_1 }, + { "2", group_A_case_2 }, + CU_TEST_INFO_NULL, +}; + +static CU_TestInfo group_B_test_cases[] = { + { "1", group_B_case_1 }, + { "2", group_B_case_2 }, + CU_TEST_INFO_NULL, +}; + +static CU_TestInfo group_C_test_cases[] = { + { "1", group_B_case_1 }, + { "1", group_B_case_2 }, /* duplicate test name */ + CU_TEST_INFO_NULL, +}; + +static CU_SuiteInfo suites0[] = { + CU_SUITE_INFO_NULL, +}; + +static CU_SuiteInfo suites1[] = { + { "A1", NULL, NULL, group_A_test_cases }, + { "B1", NULL, NULL, group_B_test_cases }, + CU_SUITE_INFO_NULL, +}; + +static CU_SuiteInfo suites2[] = { + { "A2", NULL, NULL, group_A_test_cases }, + { "B2", NULL, NULL, group_B_test_cases }, + CU_SUITE_INFO_NULL, +}; + +static CU_SuiteInfo suites3[] = { + { "A3", NULL, NULL, group_A_test_cases }, + { "A3", NULL, NULL, group_C_test_cases }, /* duplicate suite name */ + CU_SUITE_INFO_NULL, +}; + +static void test_register_suite(void) +{ + CU_pTestRegistry pReg = NULL; + CU_ErrorCode status; + + if (CU_initialize_registry()) { + fprintf(stderr, "\nError initializing registry in test_register_suite()."); + return; + } + + pReg = CU_get_registry(); + + /* test initial condition */ + TEST_FATAL(NULL != pReg); + TEST(0 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + + /* test CU_register_suites() with NULL */ + status = CU_register_suites(NULL); + TEST(CUE_SUCCESS == status); + TEST(0 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + + /* test CU_register_suites() with empty array */ + status = CU_register_suites(suites0); + TEST(CUE_SUCCESS == status); + TEST(0 == pReg->uiNumberOfSuites); + TEST(0 == pReg->uiNumberOfTests); + + /* test CU_register_suites() with ok array */ + status = CU_register_suites(suites1); + TEST(CUE_SUCCESS == status); + TEST(2 == pReg->uiNumberOfSuites); + TEST(4 == pReg->uiNumberOfTests); + + /* test CU_register_suites() with duplicate suite name */ + status = CU_register_suites(suites1); + TEST(CUE_SUCCESS == status); /* shaky - depends on order of operation in CU_register_suites() */ + TEST(4 == pReg->uiNumberOfSuites); + TEST(8 == pReg->uiNumberOfTests); + + /* test CU_register_suites() with duplicate test name */ + status = CU_register_suites(suites3); + TEST(CUE_DUP_TEST == status); /* shaky - depends on order of operation in CU_register_suites() */ + TEST(6 == pReg->uiNumberOfSuites); + TEST(12 == pReg->uiNumberOfTests); + + CU_cleanup_registry(); + + if (CU_initialize_registry()) { + fprintf(stderr, "\nError initializing registry in test_register_suite()."); + return; + } + + pReg = CU_get_registry(); + + /* test CU_register_nsuites() with ok arrays */ + status = CU_register_nsuites(2, suites1, suites2); + TEST(CUE_SUCCESS == status); + TEST(4 == pReg->uiNumberOfSuites); + TEST(8 == pReg->uiNumberOfTests); +} + +/*--------------------------------------------------*/ +void test_cunit_TestDB(void) +{ + test_cunit_start_tests("TestDB.c"); + + test_CU_initialize_registry(); + test_CU_cleanup_registry(); + test_CU_add_suite(); + test_CU_set_suite_attributes(); + test_get_suite_functions(); + test_CU_add_test(); + test_CU_set_test_attributes(); + test_get_test_functions(); + test_CU_get_registry(); + test_CU_set_registry(); + test_CU_create_new_registry(); + test_cleanup_test_registry(); + test_create_suite(); + test_insert_suite(); + test_create_test(); + test_cleanup_test(); + test_insert_test(); + test_register_suite(); + + test_cunit_end_tests(); +} + +#endif /* CUNIT_BUILD_TESTS */ diff --git a/pde-test-host/pde-test-host/cunit/TestRun.c b/pde-test-host/pde-test-host/cunit/TestRun.c new file mode 100755 index 0000000..ac6a735 --- /dev/null +++ b/pde-test-host/pde-test-host/cunit/TestRun.c @@ -0,0 +1,2913 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2001 Anil Kumar + * Copyright (C) 2004-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 Test Run Interface. + * + * Aug 2001 Initial implementaion (AK) + * + * 19/Aug/2001 Added initial registry/Suite/test framework implementation. (AK) + * + * 24/Aug/2001 Changed Data structure from SLL to DLL for all linked lists. (AK) + * + * 25/Nov/2001 Added notification for Suite Initialization failure condition. (AK) + * + * 5-Aug-2004 New interface, doxygen comments, moved add_failure on suite + * initialization so called even if a callback is not registered, + * moved CU_assertImplementation into TestRun.c, consolidated + * all run summary info out of CU_TestRegistry into TestRun.c, + * revised counting and reporting of run stats to cleanly + * differentiate suite, test, and assertion failures. (JDS) + * + * 1-Sep-2004 Modified CU_assertImplementation() and run_single_test() for + * setjmp/longjmp mechanism of aborting test runs, add asserts in + * CU_assertImplementation() to trap use outside a registered + * test function during an active test run. (JDS) + * + * 22-Sep-2004 Initial implementation of internal unit tests, added nFailureRecords + * to CU_Run_Summary, added CU_get_n_failure_records(), removed + * requirement for registry to be initialized in order to run + * CU_run_suite() and CU_run_test(). (JDS) + * + * 30-Apr-2005 Added callback for suite cleanup function failure, + * updated unit tests. (JDS) + * + * 23-Apr-2006 Added testing for suite/test deactivation, changing functions. + * Moved doxygen comments for public functions into header. + * Added type marker to CU_FailureRecord. + * Added support for tracking inactive suites/tests. (JDS) + * + * 02-May-2006 Added internationalization hooks. (JDS) + * + * 02-Jun-2006 Added support for elapsed time. Added handlers for suite + * start and complete events. Reworked test run routines to + * better support these features, suite/test activation. (JDS) + */ + +/** @file + * Test run management functions (implementation). + */ +/** @addtogroup Framework + @{ +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CUnit.h" +#include "MyMem.h" +#include "TestDB.h" +#include "TestRun.h" +#include "Util.h" +#include "CUnit_intl.h" + +#define MAX_CMD_LEN 100 + +//Extern declaration +extern int collect_syslog; + +//Callback fn declaration +typedef void (*cunit_logger_cb)(void *fn); + +/*================================================================= + * Global/Static Definitions + *=================================================================*/ +static CU_BOOL f_bTestIsRunning = CU_FALSE; /**< Flag for whether a test run is in progress */ +static CU_pSuite f_pCurSuite = NULL; /**< Pointer to the suite currently being run. */ +static CU_pTest f_pCurTest = NULL; /**< Pointer to the test currently being run. */ + +/** CU_RunSummary to hold results of each test run. */ +static CU_RunSummary f_run_summary = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +/** CU_pFailureRecord to hold head of failure record list of each test run. */ +static CU_pFailureRecord f_failure_list = NULL; + +/** CU_pFailureRecord to hold head of failure record list of each test run. */ +static CU_pFailureRecord f_last_failure = NULL; + +/** Flag for whether inactive suites/tests are treated as failures. */ +static CU_BOOL f_failure_on_inactive = CU_TRUE; + +/** Variable for storage of start time for test run. */ +static clock_t f_start_time; + + +/** Pointer to the function to be called before running a suite. */ +static CU_SuiteStartMessageHandler f_pSuiteStartMessageHandler = NULL; + +/** Pointer to the function to be called before running a test. */ +static CU_TestStartMessageHandler f_pTestStartMessageHandler = NULL; + +/** Pointer to the function to be called after running a test. */ +static CU_TestCompleteMessageHandler f_pTestCompleteMessageHandler = NULL; + +/** Pointer to the function to be called after running a suite. */ +static CU_SuiteCompleteMessageHandler f_pSuiteCompleteMessageHandler = NULL; + +/** Pointer to the function to be called when all tests have been run. */ +static CU_AllTestsCompleteMessageHandler f_pAllTestsCompleteMessageHandler = NULL; + +/** Pointer to the function to be called if a suite initialization function returns an error. */ +static CU_SuiteInitFailureMessageHandler f_pSuiteInitFailureMessageHandler = NULL; + +/** Pointer to the function to be called if a suite cleanup function returns an error. */ +static CU_SuiteCleanupFailureMessageHandler f_pSuiteCleanupFailureMessageHandler = NULL; + +/*================================================================= + * Private function forward declarations + *=================================================================*/ +static void clear_previous_results(CU_pRunSummary pRunSummary, CU_pFailureRecord* ppFailure); +static void cleanup_failure_list(CU_pFailureRecord* ppFailure); +static CU_ErrorCode run_single_suite(CU_pSuite pSuite, CU_pRunSummary pRunSummary); +static CU_ErrorCode run_single_test(CU_pTest pTest, CU_pRunSummary pRunSummary); +static void add_failure(CU_pFailureRecord* ppFailure, + CU_pRunSummary pRunSummary, + CU_FailureType type, + unsigned int uiLineNumber, + const char *szCondition, + const char *szFileName, + CU_pSuite pSuite, + CU_pTest pTest); + +/*================================================================= + * Public Interface functions + *=================================================================*/ +CU_BOOL CU_assertImplementation(CU_BOOL bValue, + unsigned int uiLine, + const char *strCondition, + const char *strFile, + const char *strFunction, + CU_BOOL bFatal) +{ + /* not used in current implementation - stop compiler warning */ + CU_UNREFERENCED_PARAMETER(strFunction); + + /* these should always be non-NULL (i.e. a test run is in progress) */ + assert(NULL != f_pCurSuite); + assert(NULL != f_pCurTest); + + ++f_run_summary.nAsserts; + if (CU_FALSE == bValue) { + ++f_run_summary.nAssertsFailed; + add_failure(&f_failure_list, &f_run_summary, CUF_AssertFailed, + uiLine, strCondition, strFile, f_pCurSuite, f_pCurTest); + + if ((CU_TRUE == bFatal) && (NULL != f_pCurTest->pJumpBuf)) { + longjmp(*(f_pCurTest->pJumpBuf), 1); + } + } + + return bValue; +} + +/*------------------------------------------------------------------------*/ +void CU_set_suite_start_handler(CU_SuiteStartMessageHandler pSuiteStartHandler) +{ + f_pSuiteStartMessageHandler = pSuiteStartHandler; +} + +/*------------------------------------------------------------------------*/ +void CU_set_test_start_handler(CU_TestStartMessageHandler pTestStartHandler) +{ + f_pTestStartMessageHandler = pTestStartHandler; +} + +/*------------------------------------------------------------------------*/ +void CU_set_test_complete_handler(CU_TestCompleteMessageHandler pTestCompleteHandler) +{ + f_pTestCompleteMessageHandler = pTestCompleteHandler; +} + +/*------------------------------------------------------------------------*/ +void CU_set_suite_complete_handler(CU_SuiteCompleteMessageHandler pSuiteCompleteHandler) +{ + f_pSuiteCompleteMessageHandler = pSuiteCompleteHandler; +} + +/*------------------------------------------------------------------------*/ +void CU_set_all_test_complete_handler(CU_AllTestsCompleteMessageHandler pAllTestsCompleteHandler) +{ + f_pAllTestsCompleteMessageHandler = pAllTestsCompleteHandler; +} + +/*------------------------------------------------------------------------*/ +void CU_set_suite_init_failure_handler(CU_SuiteInitFailureMessageHandler pSuiteInitFailureHandler) +{ + f_pSuiteInitFailureMessageHandler = pSuiteInitFailureHandler; +} + +/*------------------------------------------------------------------------*/ +void CU_set_suite_cleanup_failure_handler(CU_SuiteCleanupFailureMessageHandler pSuiteCleanupFailureHandler) +{ + f_pSuiteCleanupFailureMessageHandler = pSuiteCleanupFailureHandler; +} + +/*------------------------------------------------------------------------*/ +CU_SuiteStartMessageHandler CU_get_suite_start_handler(void) +{ + return f_pSuiteStartMessageHandler; +} + +/*------------------------------------------------------------------------*/ +CU_TestStartMessageHandler CU_get_test_start_handler(void) +{ + return f_pTestStartMessageHandler; +} + +/*------------------------------------------------------------------------*/ +CU_TestCompleteMessageHandler CU_get_test_complete_handler(void) +{ + return f_pTestCompleteMessageHandler; +} + +/*------------------------------------------------------------------------*/ +CU_SuiteCompleteMessageHandler CU_get_suite_complete_handler(void) +{ + return f_pSuiteCompleteMessageHandler; +} + +/*------------------------------------------------------------------------*/ +CU_AllTestsCompleteMessageHandler CU_get_all_test_complete_handler(void) +{ + return f_pAllTestsCompleteMessageHandler; +} + +/*------------------------------------------------------------------------*/ +CU_SuiteInitFailureMessageHandler CU_get_suite_init_failure_handler(void) +{ + return f_pSuiteInitFailureMessageHandler; +} + +/*------------------------------------------------------------------------*/ +CU_SuiteCleanupFailureMessageHandler CU_get_suite_cleanup_failure_handler(void) +{ + return f_pSuiteCleanupFailureMessageHandler; +} + +/*------------------------------------------------------------------------*/ +unsigned int CU_get_number_of_suites_run(void) +{ + return f_run_summary.nSuitesRun; +} + +/*------------------------------------------------------------------------*/ +unsigned int CU_get_number_of_suites_failed(void) +{ + return f_run_summary.nSuitesFailed; +} + +/*------------------------------------------------------------------------*/ +unsigned int CU_get_number_of_suites_inactive(void) +{ + return f_run_summary.nSuitesInactive; +} + +/*------------------------------------------------------------------------*/ +unsigned int CU_get_number_of_tests_run(void) +{ + return f_run_summary.nTestsRun; +} + +/*------------------------------------------------------------------------*/ +unsigned int CU_get_number_of_tests_failed(void) +{ + return f_run_summary.nTestsFailed; +} + +/*------------------------------------------------------------------------*/ +unsigned int CU_get_number_of_tests_inactive(void) +{ + return f_run_summary.nTestsInactive; +} + +/*------------------------------------------------------------------------*/ +unsigned int CU_get_number_of_asserts(void) +{ + return f_run_summary.nAsserts; +} + +/*------------------------------------------------------------------------*/ +unsigned int CU_get_number_of_successes(void) +{ + return (f_run_summary.nAsserts - f_run_summary.nAssertsFailed); +} + +/*------------------------------------------------------------------------*/ +unsigned int CU_get_number_of_failures(void) +{ + return f_run_summary.nAssertsFailed; +} + +/*------------------------------------------------------------------------*/ +unsigned int CU_get_number_of_failure_records(void) +{ + return f_run_summary.nFailureRecords; +} + +/*------------------------------------------------------------------------*/ +double CU_get_elapsed_time(void) +{ + if (CU_TRUE == f_bTestIsRunning) { + return ((double)clock() - (double)f_start_time)/(double)CLOCKS_PER_SEC; + } + else { + return f_run_summary.ElapsedTime; + } +} + +/*------------------------------------------------------------------------*/ +CU_pFailureRecord CU_get_failure_list(void) +{ + return f_failure_list; +} + +/*------------------------------------------------------------------------*/ +CU_pRunSummary CU_get_run_summary(void) +{ + return &f_run_summary; +} + +/*------------------------------------------------------------------------*/ +CU_ErrorCode CU_run_all_tests(void) +{ + CU_pTestRegistry pRegistry = CU_get_registry(); + CU_pSuite pSuite = NULL; + CU_ErrorCode result = CUE_SUCCESS; + CU_ErrorCode result2; + + /* Clear results from the previous run */ + clear_previous_results(&f_run_summary, &f_failure_list); + + if (NULL == pRegistry) { + result = CUE_NOREGISTRY; + } + else { + /* test run is starting - set flag */ + f_bTestIsRunning = CU_TRUE; + f_start_time = clock(); + + pSuite = pRegistry->pSuite; + while ((NULL != pSuite) && ((CUE_SUCCESS == result) || (CU_get_error_action() == CUEA_IGNORE))) { + result2 = run_single_suite(pSuite, &f_run_summary); + result = (CUE_SUCCESS == result) ? result2 : result; /* result = 1st error encountered */ + pSuite = pSuite->pNext; + } + + /* test run is complete - clear flag */ + f_bTestIsRunning = CU_FALSE; + f_run_summary.ElapsedTime = ((double)clock() - (double)f_start_time)/(double)CLOCKS_PER_SEC; + + if (NULL != f_pAllTestsCompleteMessageHandler) { + (*f_pAllTestsCompleteMessageHandler)(f_failure_list); + } + } + + CU_set_error(result); + return result; +} + +/*------------------------------------------------------------------------*/ +CU_ErrorCode CU_run_suite(CU_pSuite pSuite) +{ + CU_ErrorCode result = CUE_SUCCESS; + + /* Clear results from the previous run */ + clear_previous_results(&f_run_summary, &f_failure_list); + + if (NULL == pSuite) { + result = CUE_NOSUITE; + } + else { + /* test run is starting - set flag */ + f_bTestIsRunning = CU_TRUE; + f_start_time = clock(); + + result = run_single_suite(pSuite, &f_run_summary); + + /* test run is complete - clear flag */ + f_bTestIsRunning = CU_FALSE; + f_run_summary.ElapsedTime = ((double)clock() - (double)f_start_time)/(double)CLOCKS_PER_SEC; + + /* run handler for overall completion, if any */ + if (NULL != f_pAllTestsCompleteMessageHandler) { + (*f_pAllTestsCompleteMessageHandler)(f_failure_list); + } + } + + CU_set_error(result); + return result; +} + +/*------------------------------------------------------------------------*/ +CU_ErrorCode CU_run_test(CU_pSuite pSuite, CU_pTest pTest) +{ + CU_ErrorCode result = CUE_SUCCESS; + CU_ErrorCode result2; + + /* Clear results from the previous run */ + clear_previous_results(&f_run_summary, &f_failure_list); + + if (NULL == pSuite) { + result = CUE_NOSUITE; + } + else if (NULL == pTest) { + result = CUE_NOTEST; + } + else if (CU_FALSE == pSuite->fActive) { + f_run_summary.nSuitesInactive++; + if (CU_FALSE != f_failure_on_inactive) { + add_failure(&f_failure_list, &f_run_summary, CUF_SuiteInactive, + 0, _("Suite inactive"), _("CUnit System"), pSuite, NULL); + } + result = CUE_SUITE_INACTIVE; + } + else if ((NULL == pTest->pName) || (NULL == CU_get_test_by_name(pTest->pName, pSuite))) { + result = CUE_TEST_NOT_IN_SUITE; + } + else { + /* test run is starting - set flag */ + f_bTestIsRunning = CU_TRUE; + f_start_time = clock(); + + f_pCurTest = NULL; + f_pCurSuite = pSuite; + + /* run handler for suite start, if any */ + if (NULL != f_pSuiteStartMessageHandler) { + (*f_pSuiteStartMessageHandler)(pSuite); + } + + /* run the suite initialization function, if any */ + if ((NULL != pSuite->pInitializeFunc) && (0 != (*pSuite->pInitializeFunc)())) { + /* init function had an error - call handler, if any */ + if (NULL != f_pSuiteInitFailureMessageHandler) { + (*f_pSuiteInitFailureMessageHandler)(pSuite); + } + f_run_summary.nSuitesFailed++; + add_failure(&f_failure_list, &f_run_summary, CUF_SuiteInitFailed, 0, + _("Suite Initialization failed - Suite Skipped"), + _("CUnit System"), pSuite, NULL); + result = CUE_SINIT_FAILED; + } + /* reach here if no suite initialization, or if it succeeded */ + else { + result2 = run_single_test(pTest, &f_run_summary); + result = (CUE_SUCCESS == result) ? result2 : result; + + /* run the suite cleanup function, if any */ + if ((NULL != pSuite->pCleanupFunc) && (0 != (*pSuite->pCleanupFunc)())) { + /* cleanup function had an error - call handler, if any */ + if (NULL != f_pSuiteCleanupFailureMessageHandler) { + (*f_pSuiteCleanupFailureMessageHandler)(pSuite); + } + f_run_summary.nSuitesFailed++; + add_failure(&f_failure_list, &f_run_summary, CUF_SuiteCleanupFailed, + 0, _("Suite cleanup failed."), _("CUnit System"), pSuite, NULL); + result = (CUE_SUCCESS == result) ? CUE_SCLEAN_FAILED : result; + } + } + + /* run handler for suite completion, if any */ + if (NULL != f_pSuiteCompleteMessageHandler) { + (*f_pSuiteCompleteMessageHandler)(pSuite, NULL); + } + + /* test run is complete - clear flag */ + f_bTestIsRunning = CU_FALSE; + f_run_summary.ElapsedTime = ((double)clock() - (double)f_start_time)/(double)CLOCKS_PER_SEC; + + /* run handler for overall completion, if any */ + if (NULL != f_pAllTestsCompleteMessageHandler) { + (*f_pAllTestsCompleteMessageHandler)(f_failure_list); + } + + f_pCurSuite = NULL; + } + + CU_set_error(result); + return result; +} + +/*------------------------------------------------------------------------*/ +void CU_clear_previous_results(void) +{ + clear_previous_results(&f_run_summary, &f_failure_list); +} + +/*------------------------------------------------------------------------*/ +CU_pSuite CU_get_current_suite(void) +{ + return f_pCurSuite; +} + +/*------------------------------------------------------------------------*/ +CU_pTest CU_get_current_test(void) +{ + return f_pCurTest; +} + +/*------------------------------------------------------------------------*/ +CU_BOOL CU_is_test_running(void) +{ + return f_bTestIsRunning; +} + +/*------------------------------------------------------------------------*/ +CU_EXPORT void CU_set_fail_on_inactive(CU_BOOL new_inactive) +{ + f_failure_on_inactive = new_inactive; +} + +/*------------------------------------------------------------------------*/ +CU_EXPORT CU_BOOL CU_get_fail_on_inactive(void) +{ + return f_failure_on_inactive; +} + +/*------------------------------------------------------------------------*/ +CU_EXPORT void CU_print_run_results(FILE *file) +{ + char *summary_string; + + assert(NULL != file); + summary_string = CU_get_run_results_string(); + if (NULL != summary_string) { + fprintf(file, "%s", summary_string); + CU_FREE(summary_string); + } + else { + fprintf(file, _("An error occurred printing the run results.")); + } +} + +/*------------------------------------------------------------------------*/ +CU_EXPORT char * CU_get_run_results_string(void) + +{ + CU_pRunSummary pRunSummary = &f_run_summary; + CU_pTestRegistry pRegistry = CU_get_registry(); + int width[9]; + size_t len; + char *result; + + assert(NULL != pRunSummary); + assert(NULL != pRegistry); + + width[0] = strlen(_("Run Summary:")); + width[1] = CU_MAX(6, + CU_MAX(strlen(_("Type")), + CU_MAX(strlen(_("suites")), + CU_MAX(strlen(_("tests")), + strlen(_("asserts")))))) + 1; + width[2] = CU_MAX(6, + CU_MAX(strlen(_("Total")), + CU_MAX(CU_number_width(pRegistry->uiNumberOfSuites), + CU_MAX(CU_number_width(pRegistry->uiNumberOfTests), + CU_number_width(pRunSummary->nAsserts))))) + 1; + width[3] = CU_MAX(6, + CU_MAX(strlen(_("Ran")), + CU_MAX(CU_number_width(pRunSummary->nSuitesRun), + CU_MAX(CU_number_width(pRunSummary->nTestsRun), + CU_number_width(pRunSummary->nAsserts))))) + 1; + width[4] = CU_MAX(6, + CU_MAX(strlen(_("Passed")), + CU_MAX(strlen(_("n/a")), + CU_MAX(CU_number_width(pRunSummary->nTestsRun - pRunSummary->nTestsFailed), + CU_number_width(pRunSummary->nAsserts - pRunSummary->nAssertsFailed))))) + 1; + width[5] = CU_MAX(6, + CU_MAX(strlen(_("Failed")), + CU_MAX(CU_number_width(pRunSummary->nSuitesFailed), + CU_MAX(CU_number_width(pRunSummary->nTestsFailed), + CU_number_width(pRunSummary->nAssertsFailed))))) + 1; + width[6] = CU_MAX(6, + CU_MAX(strlen(_("Inactive")), + CU_MAX(CU_number_width(pRunSummary->nSuitesInactive), + CU_MAX(CU_number_width(pRunSummary->nTestsInactive), + strlen(_("n/a")))))) + 1; + + width[7] = strlen(_("Elapsed time = ")); + width[8] = strlen(_(" seconds")); + + len = 13 + 4*(width[0] + width[1] + width[2] + width[3] + width[4] + width[5] + width[6]) + width[7] + width[8] + 1; + result = (char *)CU_MALLOC(len); + + if (NULL != result) { + snprintf(result, len, "%*s%*s%*s%*s%*s%*s%*s\n" /* if you change this, be sure */ + "%*s%*s%*u%*u%*s%*u%*u\n" /* to change the calculation of */ + "%*s%*s%*u%*u%*u%*u%*u\n" /* len above! */ + "%*s%*s%*u%*u%*u%*u%*s\n\n" + "%*s%8.3f%*s", + width[0], _("Run Summary:"), + width[1], _("Type"), + width[2], _("Total"), + width[3], _("Ran"), + width[4], _("Passed"), + width[5], _("Failed"), + width[6], _("Inactive"), + width[0], " ", + width[1], _("suites"), + width[2], pRegistry->uiNumberOfSuites, + width[3], pRunSummary->nSuitesRun, + width[4], _("n/a"), + width[5], pRunSummary->nSuitesFailed, + width[6], pRunSummary->nSuitesInactive, + width[0], " ", + width[1], _("tests"), + width[2], pRegistry->uiNumberOfTests, + width[3], pRunSummary->nTestsRun, + width[4], pRunSummary->nTestsRun - pRunSummary->nTestsFailed, + width[5], pRunSummary->nTestsFailed, + width[6], pRunSummary->nTestsInactive, + width[0], " ", + width[1], _("asserts"), + width[2], pRunSummary->nAsserts, + width[3], pRunSummary->nAsserts, + width[4], pRunSummary->nAsserts - pRunSummary->nAssertsFailed, + width[5], pRunSummary->nAssertsFailed, + width[6], _("n/a"), + width[7], _("Elapsed time = "), CU_get_elapsed_time(), /* makes sure time is updated */ + width[8], _(" seconds") + ); + result[len-1] = '\0'; + } + return result; +} + +/*================================================================= + * Static Function Definitions + *=================================================================*/ +/** + * Records a runtime failure. + * This function is called whenever a runtime failure occurs. + * This includes user assertion failures, suite initialization and + * cleanup failures, and inactive suites/tests when set as failures. + * This function records the details of the failure in a new + * failure record in the linked list of runtime failures. + * + * @param ppFailure Pointer to head of linked list of failure + * records to append with new failure record. + * If it points to a NULL pointer, it will be set + * to point to the new failure record. + * @param pRunSummary Pointer to CU_RunSummary keeping track of failure records + * (ignored if NULL). + * @param type Type of failure. + * @param uiLineNumber Line number of the failure, if applicable. + * @param szCondition Description of failure condition + * @param szFileName Name of file, if applicable + * @param pSuite The suite being run at time of failure + * @param pTest The test being run at time of failure + */ +static void add_failure(CU_pFailureRecord* ppFailure, + CU_pRunSummary pRunSummary, + CU_FailureType type, + unsigned int uiLineNumber, + const char *szCondition, + const char *szFileName, + CU_pSuite pSuite, + CU_pTest pTest) +{ + CU_pFailureRecord pFailureNew = NULL; + CU_pFailureRecord pTemp = NULL; + + assert(NULL != ppFailure); + + pFailureNew = (CU_pFailureRecord)CU_MALLOC(sizeof(CU_FailureRecord)); + + if (NULL == pFailureNew) { + return; + } + + pFailureNew->strFileName = NULL; + pFailureNew->strCondition = NULL; + if (NULL != szFileName) { + pFailureNew->strFileName = (char*)CU_MALLOC(strlen(szFileName) + 1); + if(NULL == pFailureNew->strFileName) { + CU_FREE(pFailureNew); + return; + } + strcpy(pFailureNew->strFileName, szFileName); + } + + if (NULL != szCondition) { + pFailureNew->strCondition = (char*)CU_MALLOC(strlen(szCondition) + 1); + if (NULL == pFailureNew->strCondition) { + if(NULL != pFailureNew->strFileName) { + CU_FREE(pFailureNew->strFileName); + } + CU_FREE(pFailureNew); + return; + } + strcpy(pFailureNew->strCondition, szCondition); + } + + pFailureNew->type = type; + pFailureNew->uiLineNumber = uiLineNumber; + pFailureNew->pTest = pTest; + pFailureNew->pSuite = pSuite; + pFailureNew->pNext = NULL; + pFailureNew->pPrev = NULL; + + pTemp = *ppFailure; + if (NULL != pTemp) { + while (NULL != pTemp->pNext) { + pTemp = pTemp->pNext; + } + pTemp->pNext = pFailureNew; + pFailureNew->pPrev = pTemp; + } + else { + *ppFailure = pFailureNew; + } + + if (NULL != pRunSummary) { + ++(pRunSummary->nFailureRecords); + } + f_last_failure = pFailureNew; +} + +/* + * Local function for result set initialization/cleanup. + */ +/*------------------------------------------------------------------------*/ +/** + * Initializes the run summary information in the specified structure. + * Resets the run counts to zero, and calls cleanup_failure_list() if + * failures were recorded by the last test run. Calling this function + * multiple times, while inefficient, will not cause an error condition. + * + * @param pRunSummary CU_RunSummary to initialize (non-NULL). + * @param ppFailure The failure record to clean (non-NULL). + * @see CU_clear_previous_results() + */ +static void clear_previous_results(CU_pRunSummary pRunSummary, CU_pFailureRecord* ppFailure) +{ + assert(NULL != pRunSummary); + assert(NULL != ppFailure); + + pRunSummary->nSuitesRun = 0; + pRunSummary->nSuitesFailed = 0; + pRunSummary->nSuitesInactive = 0; + pRunSummary->nTestsRun = 0; + pRunSummary->nTestsFailed = 0; + pRunSummary->nTestsInactive = 0; + pRunSummary->nAsserts = 0; + pRunSummary->nAssertsFailed = 0; + pRunSummary->nFailureRecords = 0; + pRunSummary->ElapsedTime = 0.0; + + if (NULL != *ppFailure) { + cleanup_failure_list(ppFailure); + } + + f_last_failure = NULL; +} + +/*------------------------------------------------------------------------*/ +/** + * Frees all memory allocated for the linked list of test failure + * records. pFailure is reset to NULL after its list is cleaned up. + * + * @param ppFailure Pointer to head of linked list of + * CU_pFailureRecords to clean. + * @see CU_clear_previous_results() + */ +static void cleanup_failure_list(CU_pFailureRecord* ppFailure) +{ + CU_pFailureRecord pCurFailure = NULL; + CU_pFailureRecord pNextFailure = NULL; + + pCurFailure = *ppFailure; + + while (NULL != pCurFailure) { + + if (NULL != pCurFailure->strCondition) { + CU_FREE(pCurFailure->strCondition); + } + + if (NULL != pCurFailure->strFileName) { + CU_FREE(pCurFailure->strFileName); + } + + pNextFailure = pCurFailure->pNext; + CU_FREE(pCurFailure); + pCurFailure = pNextFailure; + } + + *ppFailure = NULL; +} + + +/* Function to collect syslog for a test */ +//FIXME find another bettwer way to do this, It is currentlly leaving tail procs in ps +void cunit_logger_fn(void *fn){ + char sys_cmd[MAX_CMD_LEN] = {'\0'}; + sprintf(sys_cmd, "tail -f /var/log/syslog > %s.txt", (char *)fn); + system("service syslog restart"); + system(sys_cmd); +} + +/*------------------------------------------------------------------------*/ +/** + * Runs all tests in a specified suite. + * Internal function to run all tests in a suite. The suite need + * not be registered in the test registry to be run. Only + * suites having their fActive flags set CU_TRUE will actually be + * run. If the CUnit framework is in an error condition after + * running a test, no additional tests are run. + * + * @param pSuite The suite containing the test (non-NULL). + * @param pRunSummary The CU_RunSummary to receive the results (non-NULL). + * @return A CU_ErrorCode indicating the status of the run. + * @see CU_run_suite() for public interface function. + * @see CU_run_all_tests() for running all suites. + */ +static CU_ErrorCode run_single_suite(CU_pSuite pSuite, CU_pRunSummary pRunSummary) +{ + CU_pTest pTest = NULL; + unsigned int nStartFailures; + /* keep track of the last failure BEFORE running the test */ + CU_pFailureRecord pLastFailure = f_last_failure; + CU_ErrorCode result = CUE_SUCCESS; + CU_ErrorCode result2; + + assert(NULL != pSuite); + assert(NULL != pRunSummary); + + nStartFailures = pRunSummary->nFailureRecords; + + f_pCurTest = NULL; + f_pCurSuite = pSuite; + + /* run handler for suite start, if any */ + if (NULL != f_pSuiteStartMessageHandler) { + (*f_pSuiteStartMessageHandler)(pSuite); + } + + /* run suite if it's active */ + if (CU_FALSE != pSuite->fActive) { + + /* run the suite initialization function, if any */ + if ((NULL != pSuite->pInitializeFunc) && (0 != (*pSuite->pInitializeFunc)())) { + /* init function had an error - call handler, if any */ + if (NULL != f_pSuiteInitFailureMessageHandler) { + (*f_pSuiteInitFailureMessageHandler)(pSuite); + } + pRunSummary->nSuitesFailed++; + add_failure(&f_failure_list, &f_run_summary, CUF_SuiteInitFailed, 0, + _("Suite Initialization failed - Suite Skipped"), + _("CUnit System"), pSuite, NULL); + result = CUE_SINIT_FAILED; + } + + /* reach here if no suite initialization, or if it succeeded */ + else { + pTest = pSuite->pTest; + while ((NULL != pTest) && ((CUE_SUCCESS == result) || (CU_get_error_action() == CUEA_IGNORE))) { + if (CU_FALSE != pTest->fActive) { + result2 = run_single_test(pTest, pRunSummary); + result = (CUE_SUCCESS == result) ? result2 : result; + } + else { + f_run_summary.nTestsInactive++; + if (CU_FALSE != f_failure_on_inactive) { + add_failure(&f_failure_list, &f_run_summary, CUF_TestInactive, + 0, _("Test inactive"), _("CUnit System"), pSuite, pTest); + result = CUE_TEST_INACTIVE; + } + } + pTest = pTest->pNext; + } + pRunSummary->nSuitesRun++; + + /* call the suite cleanup function, if any */ + if ((NULL != pSuite->pCleanupFunc) && (0 != (*pSuite->pCleanupFunc)())) { + if (NULL != f_pSuiteCleanupFailureMessageHandler) { + (*f_pSuiteCleanupFailureMessageHandler)(pSuite); + } + pRunSummary->nSuitesFailed++; + add_failure(&f_failure_list, &f_run_summary, CUF_SuiteCleanupFailed, + 0, _("Suite cleanup failed."), _("CUnit System"), pSuite, NULL); + result = (CUE_SUCCESS == result) ? CUE_SCLEAN_FAILED : result; + } + } + } + + /* otherwise record inactive suite and failure if appropriate */ + else { + f_run_summary.nSuitesInactive++; + if (CU_FALSE != f_failure_on_inactive) { + add_failure(&f_failure_list, &f_run_summary, CUF_SuiteInactive, + 0, _("Suite inactive"), _("CUnit System"), pSuite, NULL); + result = CUE_SUITE_INACTIVE; + } + } + + /* if additional failures have occurred... */ + if (pRunSummary->nFailureRecords > nStartFailures) { + if (NULL != pLastFailure) { + pLastFailure = pLastFailure->pNext; /* was a previous failure, so go to next one */ + } + else { + pLastFailure = f_failure_list; /* no previous failure - go to 1st one */ + } + } + else { + pLastFailure = NULL; /* no additional failure - set to NULL */ + } + + /* run handler for suite completion, if any */ + if (NULL != f_pSuiteCompleteMessageHandler) { + (*f_pSuiteCompleteMessageHandler)(pSuite, pLastFailure); + } + + f_pCurSuite = NULL; + return result; +} + +/*------------------------------------------------------------------------*/ +/** + * Runs a specific test. + * Internal function to run a test case. This includes calling + * any handler to be run before executing the test, running the + * test's function (if any), and calling any handler to be run + * after executing a test. Suite initialization and cleanup functions + * are not called by this function. A current suite must be set and + * active (checked by assertion). + * + * @param pTest The test to be run (non-NULL). + * @param pRunSummary The CU_RunSummary to receive the results (non-NULL). + * @return A CU_ErrorCode indicating the status of the run. + * @see CU_run_test() for public interface function. + * @see CU_run_all_tests() for running all suites. + */ +static CU_ErrorCode run_single_test(CU_pTest pTest, CU_pRunSummary pRunSummary) +{ + volatile unsigned int nStartFailures; + pthread_t tid; + int rv = 0; + cunit_logger_cb cb = cunit_logger_fn; + /* keep track of the last failure BEFORE running the test */ + volatile CU_pFailureRecord pLastFailure = f_last_failure; + jmp_buf buf; + CU_ErrorCode result = CUE_SUCCESS; + + assert(NULL != f_pCurSuite); + assert(CU_FALSE != f_pCurSuite->fActive); + assert(NULL != pTest); + assert(NULL != pRunSummary); + + nStartFailures = pRunSummary->nFailureRecords; + + f_pCurTest = pTest; + + if (NULL != f_pTestStartMessageHandler) { + (*f_pTestStartMessageHandler)(f_pCurTest, f_pCurSuite); + } + + /* run test if it is active */ + if (CU_FALSE != pTest->fActive) { + + /* set jmp_buf and run test */ + pTest->pJumpBuf = &buf; + if (0 == setjmp(buf)) { + if (NULL != pTest->pTestFunc) { + if (collect_syslog) {//FIXME Currently WIP, It is not reliable for huge batch runs now + rv = pthread_create(&tid, NULL, (void *)cb, (void *)pTest->pName); + if (rv) { + fprintf(stdout, "thread create failed for collecting syslog for %s\n",(char *)pTest->pName); + } + } + (*pTest->pTestFunc)(); + if (collect_syslog){ + sleep(1); + pthread_cancel(tid); + } + } + } + + pRunSummary->nTestsRun++; + } + else { + f_run_summary.nTestsInactive++; + if (CU_FALSE != f_failure_on_inactive) { + add_failure(&f_failure_list, &f_run_summary, CUF_TestInactive, + 0, _("Test inactive"), _("CUnit System"), f_pCurSuite, f_pCurTest); + } + result = CUE_TEST_INACTIVE; + } + + /* if additional failures have occurred... */ + if (pRunSummary->nFailureRecords > nStartFailures) { + pRunSummary->nTestsFailed++; + if (NULL != pLastFailure) { + pLastFailure = pLastFailure->pNext; /* was a previous failure, so go to next one */ + } + else { + pLastFailure = f_failure_list; /* no previous failure - go to 1st one */ + } + } + else { + pLastFailure = NULL; /* no additional failure - set to NULL */ + } + + if (NULL != f_pTestCompleteMessageHandler) { + (*f_pTestCompleteMessageHandler)(f_pCurTest, f_pCurSuite, pLastFailure); + } + + pTest->pJumpBuf = NULL; + f_pCurTest = NULL; + + return result; +} + +/** @} */ + +#ifdef CUNIT_BUILD_TESTS +#include "test_cunit.h" + +/** Types of framework events tracked by test system. */ +typedef enum TET { + SUITE_START = 1, + TEST_START, + TEST_COMPLETE, + SUITE_COMPLETE, + ALL_TESTS_COMPLETE, + SUITE_INIT_FAILED, + SUITE_CLEANUP_FAILED +} TestEventType; + +/** Test event structure for recording details of a framework event. */ +typedef struct TE { + TestEventType type; + CU_pSuite pSuite; + CU_pTest pTest; + CU_pFailureRecord pFailure; + struct TE * pNext; +} TestEvent, * pTestEvent; + +static int f_nTestEvents = 0; +static pTestEvent f_pFirstEvent = NULL; + +/** Creates & stores a test event record having the specified details. */ +static void add_test_event(TestEventType type, CU_pSuite psuite, + CU_pTest ptest, CU_pFailureRecord pfailure) +{ + pTestEvent pNewEvent = (pTestEvent)malloc(sizeof(TestEvent)); + pTestEvent pNextEvent = f_pFirstEvent; + + if (NULL == pNewEvent) { + fprintf(stderr, "Memory allocation failed in add_test_event()."); + exit(1); + } + + pNewEvent->type = type; + pNewEvent->pSuite = psuite; + pNewEvent->pTest = ptest; + pNewEvent->pFailure = pfailure; + pNewEvent->pNext = NULL; + + if (pNextEvent) { + while (pNextEvent->pNext) { + pNextEvent = pNextEvent->pNext; + } + pNextEvent->pNext = pNewEvent; + } + else { + f_pFirstEvent = pNewEvent; + } + ++f_nTestEvents; +} + +/** Deallocates all test event data. */ +static void clear_test_events(void) +{ + pTestEvent pCurrentEvent = f_pFirstEvent; + pTestEvent pNextEvent = NULL; + + while (pCurrentEvent) { + pNextEvent = pCurrentEvent->pNext; + free(pCurrentEvent); + pCurrentEvent = pNextEvent; + } + + f_pFirstEvent = NULL; + f_nTestEvents = 0; +} + +static void suite_start_handler(const CU_pSuite pSuite) +{ + TEST(CU_is_test_running()); + TEST(pSuite == CU_get_current_suite()); + TEST(NULL == CU_get_current_test()); + + add_test_event(SUITE_START, pSuite, NULL, NULL); +} + +static void test_start_handler(const CU_pTest pTest, const CU_pSuite pSuite) +{ + TEST(CU_is_test_running()); + TEST(pSuite == CU_get_current_suite()); + TEST(pTest == CU_get_current_test()); + + add_test_event(TEST_START, pSuite, pTest, NULL); +} + +static void test_complete_handler(const CU_pTest pTest, const CU_pSuite pSuite, + const CU_pFailureRecord pFailure) +{ + TEST(CU_is_test_running()); + TEST(pSuite == CU_get_current_suite()); + TEST(pTest == CU_get_current_test()); + + add_test_event(TEST_COMPLETE, pSuite, pTest, pFailure); +} + +static void suite_complete_handler(const CU_pSuite pSuite, + const CU_pFailureRecord pFailure) +{ + TEST(CU_is_test_running()); + TEST(pSuite == CU_get_current_suite()); + TEST(NULL == CU_get_current_test()); + + add_test_event(SUITE_COMPLETE, pSuite, NULL, pFailure); +} + +static void test_all_complete_handler(const CU_pFailureRecord pFailure) +{ + TEST(!CU_is_test_running()); + + add_test_event(ALL_TESTS_COMPLETE, NULL, NULL, pFailure); +} + +static void suite_init_failure_handler(const CU_pSuite pSuite) +{ + TEST(CU_is_test_running()); + TEST(pSuite == CU_get_current_suite()); + + add_test_event(SUITE_INIT_FAILED, pSuite, NULL, NULL); +} + +static void suite_cleanup_failure_handler(const CU_pSuite pSuite) +{ + TEST(CU_is_test_running()); + TEST(pSuite == CU_get_current_suite()); + + add_test_event(SUITE_CLEANUP_FAILED, pSuite, NULL, NULL); +} + +/** + * Centralize test result testing - we're going to do it a lot! + * This is messy since we want to report the calling location upon failure. + * + * Via calling test functions tests: + * CU_get_number_of_suites_run() + * CU_get_number_of_suites_failed() + * CU_get_number_of_tests_run() + * CU_get_number_of_tests_failed() + * CU_get_number_of_asserts() + * CU_get_number_of_successes() + * CU_get_number_of_failures() + * CU_get_number_of_failure_records() + * CU_get_run_summary() + */ +static void do_test_results(unsigned int nSuitesRun, + unsigned int nSuitesFailed, + unsigned int nSuitesInactive, + unsigned int nTestsRun, + unsigned int nTestsFailed, + unsigned int nTestsInactive, + unsigned int nAsserts, + unsigned int nSuccesses, + unsigned int nFailures, + unsigned int nFailureRecords, + const char *file, + unsigned int line) +{ + char msg[500]; + CU_pRunSummary pRunSummary = NULL; + + if (nSuitesRun == CU_get_number_of_suites_run()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_suites_run() (called from %s:%u)", + nSuitesRun, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + if (nSuitesInactive == CU_get_number_of_suites_inactive()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_suites_inactive() (called from %s:%u)", + nSuitesInactive, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + if (nSuitesFailed == CU_get_number_of_suites_failed()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_suites_failed() (called from %s:%u)", + nSuitesFailed, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + if (nTestsRun == CU_get_number_of_tests_run()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_tests_run() (called from %s:%u)", + nTestsRun, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + if (nTestsFailed == CU_get_number_of_tests_failed()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_tests_failed() (called from %s:%u)", + nTestsFailed, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + if (nTestsInactive == CU_get_number_of_tests_inactive()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_tests_inactive() (called from %s:%u)", + nTestsInactive, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + if (nAsserts == CU_get_number_of_asserts()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_asserts() (called from %s:%u)", + nAsserts, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + if (nSuccesses == CU_get_number_of_successes()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_successes() (called from %s:%u)", + nSuccesses, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + if (nFailures == CU_get_number_of_failures()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_failures() (called from %s:%u)", + nFailures, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + if (nFailureRecords == CU_get_number_of_failure_records()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_failure_records() (called from %s:%u)", + nFailureRecords, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + pRunSummary = CU_get_run_summary(); + + if (pRunSummary->nSuitesRun == CU_get_number_of_suites_run()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_suites_run() (called from %s:%u)", + pRunSummary->nSuitesRun, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + if (pRunSummary->nSuitesFailed == CU_get_number_of_suites_failed()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_suites_failed() (called from %s:%u)", + pRunSummary->nSuitesFailed, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + if (pRunSummary->nTestsRun == CU_get_number_of_tests_run()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_tests_run() (called from %s:%u)", + pRunSummary->nTestsRun, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + if (pRunSummary->nTestsFailed == CU_get_number_of_tests_failed()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_tests_failed() (called from %s:%u)", + pRunSummary->nTestsFailed, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + if (pRunSummary->nAsserts == CU_get_number_of_asserts()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_asserts() (called from %s:%u)", + pRunSummary->nAsserts, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + if (pRunSummary->nAssertsFailed == CU_get_number_of_failures()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_failures() (called from %s:%u)", + pRunSummary->nAssertsFailed, file, line); + msg[499] = '\0'; + FAIL(msg); + } + + if (pRunSummary->nFailureRecords == CU_get_number_of_failure_records()) { + PASS(); + } else { + snprintf(msg, 499, "%u == CU_get_number_of_failure_records() (called from %s:%u)", + pRunSummary->nFailureRecords, file, line); + msg[499] = '\0'; + FAIL(msg); + } +} + +#define test_results(nSuitesRun, nSuitesFailed, nSuitesInactive, nTestsRun, nTestsFailed, \ + nTestsInactive, nAsserts, nSuccesses, nFailures, nFailureRecords) \ + do_test_results(nSuitesRun, nSuitesFailed, nSuitesInactive, nTestsRun, nTestsFailed, \ + nTestsInactive, nAsserts, nSuccesses, nFailures, nFailureRecords, \ + __FILE__, __LINE__) + +static void test_succeed(void) { CU_TEST(CU_TRUE); } +static void test_fail(void) { CU_TEST(CU_FALSE); } +static int suite_succeed(void) { return 0; } +static int suite_fail(void) { return 1; } + +/*-------------------------------------------------*/ +/* tests: + * CU_set_suite_start_handler() + * CU_set_test_start_handler() + * CU_set_test_complete_handler() + * CU_set_suite_complete_handler() + * CU_set_all_test_complete_handler() + * CU_set_suite_init_failure_handler() + * CU_set_suite_cleanup_failure_handler() + * CU_get_suite_start_handler() + * CU_get_test_start_handler() + * CU_get_test_complete_handler() + * CU_get_suite_complete_handler() + * CU_get_all_test_complete_handler() + * CU_get_suite_init_failure_handler() + * CU_get_suite_cleanup_failure_handler() + * CU_is_test_running() + * via handlers tests: + * CU_get_current_suite() + * CU_get_current_test() + */ +static void test_message_handlers(void) +{ + CU_pSuite pSuite1 = NULL; + CU_pSuite pSuite2 = NULL; + CU_pSuite pSuite3 = NULL; + CU_pTest pTest1 = NULL; + CU_pTest pTest2 = NULL; + CU_pTest pTest3 = NULL; + CU_pTest pTest4 = NULL; + CU_pTest pTest5 = NULL; + pTestEvent pEvent = NULL; + + TEST(!CU_is_test_running()); + + /* handlers should be NULL on startup */ + TEST(NULL == CU_get_suite_start_handler()); + TEST(NULL == CU_get_test_start_handler()); + TEST(NULL == CU_get_test_complete_handler()); + TEST(NULL == CU_get_suite_complete_handler()); + TEST(NULL == CU_get_all_test_complete_handler()); + TEST(NULL == CU_get_suite_init_failure_handler()); + TEST(NULL == CU_get_suite_cleanup_failure_handler()); + + /* register some suites and tests */ + CU_initialize_registry(); + pSuite1 = CU_add_suite("suite1", NULL, NULL); + pTest1 = CU_add_test(pSuite1, "test1", test_succeed); + pTest2 = CU_add_test(pSuite1, "test2", test_fail); + pTest3 = CU_add_test(pSuite1, "test3", test_succeed); + pSuite2 = CU_add_suite("suite2", suite_fail, NULL); + pTest4 = CU_add_test(pSuite2, "test4", test_succeed); + pSuite3 = CU_add_suite("suite3", suite_succeed, suite_fail); + pTest5 = CU_add_test(pSuite3, "test5", test_fail); + + TEST_FATAL(CUE_SUCCESS == CU_get_error()); + + /* first run tests without handlers set */ + clear_test_events(); + CU_run_all_tests(); + + TEST(0 == f_nTestEvents); + TEST(NULL == f_pFirstEvent); + test_results(2,2,0,4,2,0,4,2,2,4); + + /* set handlers to local functions */ + CU_set_suite_start_handler(&suite_start_handler); + CU_set_test_start_handler(&test_start_handler); + CU_set_test_complete_handler(&test_complete_handler); + CU_set_suite_complete_handler(&suite_complete_handler); + CU_set_all_test_complete_handler(&test_all_complete_handler); + CU_set_suite_init_failure_handler(&suite_init_failure_handler); + CU_set_suite_cleanup_failure_handler(&suite_cleanup_failure_handler); + + /* confirm handlers set properly */ + TEST(suite_start_handler == CU_get_suite_start_handler()); + TEST(test_start_handler == CU_get_test_start_handler()); + TEST(test_complete_handler == CU_get_test_complete_handler()); + TEST(suite_complete_handler == CU_get_suite_complete_handler()); + TEST(test_all_complete_handler == CU_get_all_test_complete_handler()); + TEST(suite_init_failure_handler == CU_get_suite_init_failure_handler()); + TEST(suite_cleanup_failure_handler == CU_get_suite_cleanup_failure_handler()); + + /* run tests again with handlers set */ + clear_test_events(); + CU_run_all_tests(); + + TEST(17 == f_nTestEvents); + if (17 == f_nTestEvents) { + pEvent = f_pFirstEvent; + TEST(SUITE_START == pEvent->type); + TEST(pSuite1 == pEvent->pSuite); + TEST(NULL == pEvent->pTest); + TEST(NULL == pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(TEST_START == pEvent->type); + TEST(pSuite1 == pEvent->pSuite); + TEST(pTest1 == pEvent->pTest); + TEST(NULL == pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(TEST_COMPLETE == pEvent->type); + TEST(pSuite1 == pEvent->pSuite); + TEST(pTest1 == pEvent->pTest); + TEST(NULL == pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(TEST_START == pEvent->type); + TEST(pSuite1 == pEvent->pSuite); + TEST(pTest2 == pEvent->pTest); + TEST(NULL == pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(TEST_COMPLETE == pEvent->type); + TEST(pSuite1 == pEvent->pSuite); + TEST(pTest2 == pEvent->pTest); + TEST(NULL != pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(TEST_START == pEvent->type); + TEST(pSuite1 == pEvent->pSuite); + TEST(pTest3 == pEvent->pTest); + TEST(NULL == pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(TEST_COMPLETE == pEvent->type); + TEST(pSuite1 == pEvent->pSuite); + TEST(pTest3 == pEvent->pTest); + TEST(NULL == pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(SUITE_COMPLETE == pEvent->type); + TEST(pSuite1 == pEvent->pSuite); + TEST(NULL == pEvent->pTest); + TEST(NULL != pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(SUITE_START == pEvent->type); + TEST(pSuite2 == pEvent->pSuite); + TEST(NULL == pEvent->pTest); + TEST(NULL == pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(SUITE_INIT_FAILED == pEvent->type); + TEST(pSuite2 == pEvent->pSuite); + TEST(NULL == pEvent->pTest); + TEST(NULL == pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(SUITE_COMPLETE == pEvent->type); + TEST(pSuite2 == pEvent->pSuite); + TEST(NULL == pEvent->pTest); + TEST(NULL != pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(SUITE_START == pEvent->type); + TEST(pSuite3 == pEvent->pSuite); + TEST(NULL == pEvent->pTest); + TEST(NULL == pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(TEST_START == pEvent->type); + TEST(pSuite3 == pEvent->pSuite); + TEST(pTest5 == pEvent->pTest); + TEST(NULL == pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(TEST_COMPLETE == pEvent->type); + TEST(pSuite3 == pEvent->pSuite); + TEST(pTest5 == pEvent->pTest); + TEST(NULL != pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(SUITE_CLEANUP_FAILED == pEvent->type); + TEST(pSuite3 == pEvent->pSuite); + TEST(NULL == pEvent->pTest); + TEST(NULL == pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(SUITE_COMPLETE == pEvent->type); + TEST(pSuite3 == pEvent->pSuite); + TEST(NULL == pEvent->pTest); + TEST(NULL != pEvent->pFailure); + + pEvent = pEvent->pNext; + TEST(ALL_TESTS_COMPLETE == pEvent->type); + TEST(NULL == pEvent->pSuite); + TEST(NULL == pEvent->pTest); + TEST(NULL != pEvent->pFailure); + if (4 == CU_get_number_of_failure_records()) { + TEST(NULL != pEvent->pFailure->pNext); + TEST(NULL != pEvent->pFailure->pNext->pNext); + TEST(NULL != pEvent->pFailure->pNext->pNext->pNext); + TEST(NULL == pEvent->pFailure->pNext->pNext->pNext->pNext); + } + TEST(pEvent->pFailure == CU_get_failure_list()); + } + + test_results(2,2,0,4,2,0,4,2,2,4); + + /* clear handlers and run again */ + CU_set_suite_start_handler(NULL); + CU_set_test_start_handler(NULL); + CU_set_test_complete_handler(NULL); + CU_set_suite_complete_handler(NULL); + CU_set_all_test_complete_handler(NULL); + CU_set_suite_init_failure_handler(NULL); + CU_set_suite_cleanup_failure_handler(NULL); + + TEST(NULL == CU_get_suite_start_handler()); + TEST(NULL == CU_get_test_start_handler()); + TEST(NULL == CU_get_test_complete_handler()); + TEST(NULL == CU_get_suite_complete_handler()); + TEST(NULL == CU_get_all_test_complete_handler()); + TEST(NULL == CU_get_suite_init_failure_handler()); + TEST(NULL == CU_get_suite_cleanup_failure_handler()); + + clear_test_events(); + CU_run_all_tests(); + + TEST(0 == f_nTestEvents); + TEST(NULL == f_pFirstEvent); + test_results(2,2,0,4,2,0,4,2,2,4); + + CU_cleanup_registry(); + clear_test_events(); +} + +static CU_BOOL f_exit_called = CU_FALSE; + +/* intercept exit for testing of CUEA_ABORT action */ +void test_exit(int status) +{ + CU_UNREFERENCED_PARAMETER(status); /* not used */ + f_exit_called = CU_TRUE; +} + + +/*-------------------------------------------------*/ +static void test_CU_fail_on_inactive(void) +{ + CU_pSuite pSuite1 = NULL; + CU_pSuite pSuite2 = NULL; + CU_pTest pTest1 = NULL; + CU_pTest pTest2 = NULL; + CU_pTest pTest3 = NULL; + CU_pTest pTest4 = NULL; + + CU_set_error_action(CUEA_IGNORE); + CU_initialize_registry(); + + /* register some suites and tests */ + CU_initialize_registry(); + pSuite1 = CU_add_suite("suite1", NULL, NULL); + pTest1 = CU_add_test(pSuite1, "test1", test_succeed); + pTest2 = CU_add_test(pSuite1, "test2", test_fail); + pSuite2 = CU_add_suite("suite2", suite_fail, NULL); + pTest3 = CU_add_test(pSuite2, "test3", test_succeed); + pTest4 = CU_add_test(pSuite2, "test4", test_succeed); + + /* test initial conditions */ + TEST(CU_TRUE == CU_get_fail_on_inactive()); + TEST(CU_TRUE == pSuite1->fActive); + TEST(CU_TRUE == pSuite2->fActive); + TEST(CU_TRUE == pTest1->fActive); + TEST(CU_TRUE == pTest2->fActive); + TEST(CU_TRUE == pTest3->fActive); + TEST(CU_TRUE == pTest4->fActive); + + CU_set_fail_on_inactive(CU_TRUE); + TEST(CU_TRUE == CU_get_fail_on_inactive()); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* all suites/tests active */ + test_results(1,1,0,2,1,0,2,1,1,2); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CU_FALSE == CU_get_fail_on_inactive()); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); + test_results(1,1,0,2,1,0,2,1,1,2); + + CU_set_suite_active(pSuite1, CU_FALSE); + CU_set_suite_active(pSuite2, CU_FALSE); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_SUITE_INACTIVE == CU_run_all_tests()); /* all suites inactive */ + test_results(0,0,2,0,0,0,0,0,0,2); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SUCCESS == CU_run_all_tests()); + test_results(0,0,2,0,0,0,0,0,0,0); + CU_set_suite_active(pSuite1, CU_TRUE); + CU_set_suite_active(pSuite2, CU_TRUE); + + CU_set_suite_active(pSuite2, CU_FALSE); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_SUITE_INACTIVE == CU_run_all_tests()); /* some suites inactive */ + test_results(1,0,1,2,1,0,2,1,1,2); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SUCCESS == CU_run_all_tests()); + test_results(1,0,1,2,1,0,2,1,1,1); + CU_set_suite_active(pSuite2, CU_TRUE); + + CU_set_test_active(pTest1, CU_FALSE); + CU_set_test_active(pTest2, CU_FALSE); + CU_set_test_active(pTest3, CU_FALSE); + CU_set_test_active(pTest4, CU_FALSE); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_all_tests()); /* all tests inactive */ + test_results(1,1,0,0,0,2,0,0,0,3); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); + test_results(1,1,0,0,0,2,0,0,0,1); + CU_set_test_active(pTest1, CU_TRUE); + CU_set_test_active(pTest2, CU_TRUE); + CU_set_test_active(pTest3, CU_TRUE); + CU_set_test_active(pTest4, CU_TRUE); + + CU_set_test_active(pTest2, CU_FALSE); + CU_set_test_active(pTest4, CU_FALSE); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_all_tests()); /* some tests inactive */ + test_results(1,1,0,1,0,1,1,1,0,2); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); + test_results(1,1,0,1,0,1,1,1,0,1); + CU_set_test_active(pTest2, CU_TRUE); + CU_set_test_active(pTest4, CU_TRUE); + + CU_set_suite_active(pSuite2, CU_FALSE); + CU_set_test_active(pTest1, CU_FALSE); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_all_tests()); /* some suites & tests inactive */ + test_results(1,0,1,1,1,1,1,0,1,3); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SUCCESS == CU_run_all_tests()); + test_results(1,0,1,1,1,1,1,0,1,1); + CU_set_suite_active(pSuite2, CU_TRUE); + CU_set_test_active(pTest1, CU_TRUE); + + /* clean up */ + CU_cleanup_registry(); +} + +/*-------------------------------------------------*/ +static void test_CU_run_all_tests(void) +{ + CU_pSuite pSuite1 = NULL; + CU_pSuite pSuite2 = NULL; + CU_pSuite pSuite3 = NULL; + CU_pSuite pSuite4 = NULL; + CU_pTest pTest1 = NULL; + CU_pTest pTest2 = NULL; + CU_pTest pTest3 = NULL; + CU_pTest pTest4 = NULL; + CU_pTest pTest5 = NULL; + CU_pTest pTest6 = NULL; + CU_pTest pTest7 = NULL; + CU_pTest pTest8 = NULL; + CU_pTest pTest9 = NULL; + CU_pTest pTest10 = NULL; + + /* error - uninitialized registry (CUEA_IGNORE) */ + CU_cleanup_registry(); + CU_set_error_action(CUEA_IGNORE); + + TEST(CUE_NOREGISTRY == CU_run_all_tests()); + TEST(CUE_NOREGISTRY == CU_get_error()); + + /* error - uninitialized registry (CUEA_FAIL) */ + CU_cleanup_registry(); + CU_set_error_action(CUEA_FAIL); + + TEST(CUE_NOREGISTRY == CU_run_all_tests()); + TEST(CUE_NOREGISTRY == CU_get_error()); + + /* error - uninitialized registry (CUEA_ABORT) */ + CU_cleanup_registry(); + CU_set_error_action(CUEA_ABORT); + + f_exit_called = CU_FALSE; + CU_run_all_tests(); + TEST(CU_TRUE == f_exit_called); + f_exit_called = CU_FALSE; + + /* run with no suites or tests registered */ + CU_initialize_registry(); + + CU_set_error_action(CUEA_IGNORE); + TEST(CUE_SUCCESS == CU_run_all_tests()); + test_results(0,0,0,0,0,0,0,0,0,0); + + /* register some suites and tests */ + CU_initialize_registry(); + pSuite1 = CU_add_suite("suite1", NULL, NULL); + pTest1 = CU_add_test(pSuite1, "test1", test_succeed); + pTest2 = CU_add_test(pSuite1, "test2", test_fail); + pTest3 = CU_add_test(pSuite1, "test1", test_succeed); /* duplicate test name OK */ + pTest4 = CU_add_test(pSuite1, "test4", test_fail); + pTest5 = CU_add_test(pSuite1, "test1", test_succeed); /* duplicate test name OK */ + pSuite2 = CU_add_suite("suite2", suite_fail, NULL); + pTest6 = CU_add_test(pSuite2, "test6", test_succeed); + pTest7 = CU_add_test(pSuite2, "test7", test_succeed); + pSuite3 = CU_add_suite("suite1", NULL, NULL); /* duplicate suite name OK */ + pTest8 = CU_add_test(pSuite3, "test8", test_fail); + pTest9 = CU_add_test(pSuite3, "test9", test_succeed); + pSuite4 = CU_add_suite("suite4", NULL, suite_fail); + pTest10 = CU_add_test(pSuite4, "test10", test_succeed); + + TEST_FATAL(4 == CU_get_registry()->uiNumberOfSuites); + TEST_FATAL(10 == CU_get_registry()->uiNumberOfTests); + + /* run all tests (CUEA_IGNORE) */ + CU_set_error_action(CUEA_IGNORE); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* all suites/tests active */ + test_results(3,2,0,8,3,0,8,5,3,5); + + CU_set_suite_active(pSuite1, CU_FALSE); + CU_set_suite_active(pSuite2, CU_FALSE); + CU_set_suite_active(pSuite3, CU_FALSE); + CU_set_suite_active(pSuite4, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SUCCESS == CU_run_all_tests()); /* suites inactive */ + test_results(0,0,4,0,0,0,0,0,0,0); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_SUITE_INACTIVE == CU_run_all_tests()); + test_results(0,0,4,0,0,0,0,0,0,4); + + CU_set_suite_active(pSuite1, CU_FALSE); + CU_set_suite_active(pSuite2, CU_TRUE); + CU_set_suite_active(pSuite3, CU_TRUE); + CU_set_suite_active(pSuite4, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* some suites inactive */ + test_results(1,1,2,2,1,0,2,1,1,2); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_SUITE_INACTIVE == CU_run_all_tests()); + test_results(1,1,2,2,1,0,2,1,1,4); + + CU_set_suite_active(pSuite1, CU_TRUE); + CU_set_suite_active(pSuite2, CU_TRUE); + CU_set_suite_active(pSuite3, CU_TRUE); + CU_set_suite_active(pSuite4, CU_TRUE); + + CU_set_test_active(pTest1, CU_FALSE); + CU_set_test_active(pTest2, CU_FALSE); + CU_set_test_active(pTest3, CU_FALSE); + CU_set_test_active(pTest4, CU_FALSE); + CU_set_test_active(pTest5, CU_FALSE); + CU_set_test_active(pTest6, CU_FALSE); + CU_set_test_active(pTest7, CU_FALSE); + CU_set_test_active(pTest8, CU_FALSE); + CU_set_test_active(pTest9, CU_FALSE); + CU_set_test_active(pTest10, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* no tests active */ + test_results(3,2,0,0,0,8,0,0,0,2); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_all_tests()); + test_results(3,2,0,0,0,8,0,0,0,10); + + CU_set_test_active(pTest1, CU_TRUE); + CU_set_test_active(pTest2, CU_FALSE); + CU_set_test_active(pTest3, CU_TRUE); + CU_set_test_active(pTest4, CU_FALSE); + CU_set_test_active(pTest5, CU_TRUE); + CU_set_test_active(pTest6, CU_FALSE); + CU_set_test_active(pTest7, CU_TRUE); + CU_set_test_active(pTest8, CU_FALSE); + CU_set_test_active(pTest9, CU_TRUE); + CU_set_test_active(pTest10, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* some tests active */ + test_results(3,2,0,4,0,4,4,4,0,2); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_all_tests()); + test_results(3,2,0,4,0,4,4,4,0,6); + + CU_set_test_active(pTest1, CU_TRUE); + CU_set_test_active(pTest2, CU_TRUE); + CU_set_test_active(pTest3, CU_TRUE); + CU_set_test_active(pTest4, CU_TRUE); + CU_set_test_active(pTest5, CU_TRUE); + CU_set_test_active(pTest6, CU_TRUE); + CU_set_test_active(pTest7, CU_TRUE); + CU_set_test_active(pTest8, CU_TRUE); + CU_set_test_active(pTest9, CU_TRUE); + CU_set_test_active(pTest10, CU_TRUE); + + CU_set_suite_initfunc(pSuite1, &suite_fail); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* change a suite init function */ + CU_set_suite_initfunc(pSuite1, NULL); + test_results(2,3,0,3,1,0,3,2,1,4); + + CU_set_suite_cleanupfunc(pSuite4, NULL); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* change a suite cleanup function */ + CU_set_suite_cleanupfunc(pSuite4, &suite_fail); + test_results(3,1,0,8,3,0,8,5,3,4); + + CU_set_test_func(pTest2, &test_succeed); + CU_set_test_func(pTest4, &test_succeed); + CU_set_test_func(pTest8, &test_succeed); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* change a test function */ + CU_set_test_func(pTest2, &test_fail); + CU_set_test_func(pTest4, &test_fail); + CU_set_test_func(pTest8, &test_fail); + test_results(3,2,0,8,0,0,8,8,0,2); + + /* run all tests (CUEA_FAIL) */ + CU_set_error_action(CUEA_FAIL); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* all suites active */ + test_results(1,1,0,5,2,0,5,3,2,3); + + CU_set_suite_active(pSuite1, CU_TRUE); + CU_set_suite_active(pSuite2, CU_FALSE); + CU_set_suite_active(pSuite3, CU_FALSE); + CU_set_suite_active(pSuite4, CU_TRUE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SCLEAN_FAILED == CU_run_all_tests()); /* some suites inactive */ + test_results(2,1,2,6,2,0,6,4,2,3); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_SUITE_INACTIVE == CU_run_all_tests()); + test_results(1,0,1,5,2,0,5,3,2,3); + + CU_set_suite_active(pSuite1, CU_TRUE); + CU_set_suite_active(pSuite2, CU_TRUE); + CU_set_suite_active(pSuite3, CU_TRUE); + CU_set_suite_active(pSuite4, CU_TRUE); + + CU_set_test_active(pTest1, CU_FALSE); + CU_set_test_active(pTest2, CU_FALSE); + CU_set_test_active(pTest3, CU_FALSE); + CU_set_test_active(pTest4, CU_FALSE); + CU_set_test_active(pTest5, CU_FALSE); + CU_set_test_active(pTest6, CU_FALSE); + CU_set_test_active(pTest7, CU_FALSE); + CU_set_test_active(pTest8, CU_FALSE); + CU_set_test_active(pTest9, CU_FALSE); + CU_set_test_active(pTest10, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* no tests active */ + test_results(1,1,0,0,0,5,0,0,0,1); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_all_tests()); + test_results(1,0,0,0,0,1,0,0,0,1); + + CU_set_test_active(pTest1, CU_FALSE); + CU_set_test_active(pTest2, CU_TRUE); + CU_set_test_active(pTest3, CU_FALSE); + CU_set_test_active(pTest4, CU_TRUE); + CU_set_test_active(pTest5, CU_FALSE); + CU_set_test_active(pTest6, CU_TRUE); + CU_set_test_active(pTest7, CU_FALSE); + CU_set_test_active(pTest8, CU_TRUE); + CU_set_test_active(pTest9, CU_FALSE); + CU_set_test_active(pTest10, CU_TRUE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* some tests active */ + test_results(1,1,0,2,2,3,2,0,2,3); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_all_tests()); + test_results(1,0,0,0,0,1,0,0,0,1); + + CU_set_test_active(pTest1, CU_TRUE); + CU_set_test_active(pTest2, CU_TRUE); + CU_set_test_active(pTest3, CU_TRUE); + CU_set_test_active(pTest4, CU_TRUE); + CU_set_test_active(pTest5, CU_TRUE); + CU_set_test_active(pTest6, CU_TRUE); + CU_set_test_active(pTest7, CU_TRUE); + CU_set_test_active(pTest8, CU_TRUE); + CU_set_test_active(pTest9, CU_TRUE); + CU_set_test_active(pTest10, CU_TRUE); + + CU_set_suite_initfunc(pSuite2, NULL); + TEST(CUE_SCLEAN_FAILED == CU_run_all_tests()); /* change a suite init function */ + CU_set_suite_initfunc(pSuite2, &suite_fail); + test_results(4,1,0,10,3,0,10,7,3,4); + + CU_set_suite_cleanupfunc(pSuite1, &suite_fail); + TEST(CUE_SCLEAN_FAILED == CU_run_all_tests()); /* change a suite cleanup function */ + CU_set_suite_cleanupfunc(pSuite1, NULL); + test_results(1,1,0,5,2,0,5,3,2,3); + + CU_set_test_func(pTest1, &test_fail); + CU_set_test_func(pTest3, &test_fail); + CU_set_test_func(pTest5, &test_fail); + CU_set_test_func(pTest9, &test_fail); + CU_set_test_func(pTest10, &test_fail); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* change a test function */ + CU_set_test_func(pTest1, &test_succeed); + CU_set_test_func(pTest3, &test_succeed); + CU_set_test_func(pTest5, &test_succeed); + CU_set_test_func(pTest9, &test_succeed); + CU_set_test_func(pTest10, &test_succeed); + test_results(1,1,0,5,5,0,5,0,5,6); + + /* run all tests (CUEA_ABORT) */ + f_exit_called = CU_FALSE; + CU_set_error_action(CUEA_ABORT); + CU_set_suite_active(pSuite1, CU_TRUE); + CU_set_suite_active(pSuite2, CU_TRUE); + CU_set_suite_active(pSuite3, CU_TRUE); + CU_set_suite_active(pSuite4, CU_TRUE); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* all suites active */ + TEST(CU_TRUE == f_exit_called); + test_results(1,1,0,5,2,0,5,3,2,3); + + CU_set_suite_active(pSuite1, CU_FALSE); + CU_set_suite_active(pSuite2, CU_FALSE); + CU_set_suite_active(pSuite3, CU_FALSE); + CU_set_suite_active(pSuite4, CU_FALSE); + f_exit_called = CU_FALSE; + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SUCCESS == CU_run_all_tests()); /* no suites active, so no abort() */ + TEST(CU_FALSE == f_exit_called); + test_results(0,0,4,0,0,0,0,0,0,0); + f_exit_called = CU_FALSE; + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_SUITE_INACTIVE == CU_run_all_tests()); + TEST(CU_TRUE == f_exit_called); + test_results(0,0,1,0,0,0,0,0,0,1); + + CU_set_suite_active(pSuite1, CU_TRUE); + CU_set_suite_active(pSuite2, CU_FALSE); + CU_set_suite_active(pSuite3, CU_TRUE); + CU_set_suite_active(pSuite4, CU_TRUE); + f_exit_called = CU_FALSE; + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SCLEAN_FAILED == CU_run_all_tests()); /* some suites active */ + TEST(CU_TRUE == f_exit_called); + test_results(3,1,1,8,3,0,8,5,3,4); + f_exit_called = CU_FALSE; + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_SUITE_INACTIVE == CU_run_all_tests()); + TEST(CU_TRUE == f_exit_called); + test_results(1,0,1,5,2,0,5,3,2,3); + + CU_set_suite_active(pSuite1, CU_TRUE); + CU_set_suite_active(pSuite2, CU_TRUE); + CU_set_suite_active(pSuite3, CU_TRUE); + CU_set_suite_active(pSuite4, CU_TRUE); + + CU_set_test_active(pTest1, CU_FALSE); + CU_set_test_active(pTest2, CU_FALSE); + CU_set_test_active(pTest3, CU_FALSE); + CU_set_test_active(pTest4, CU_FALSE); + CU_set_test_active(pTest5, CU_FALSE); + CU_set_test_active(pTest6, CU_FALSE); + CU_set_test_active(pTest7, CU_FALSE); + CU_set_test_active(pTest8, CU_FALSE); + CU_set_test_active(pTest9, CU_FALSE); + CU_set_test_active(pTest10, CU_FALSE); + f_exit_called = CU_FALSE; + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* no tests active */ + TEST(CU_TRUE == f_exit_called); + test_results(1,1,0,0,0,5,0,0,0,1); + f_exit_called = CU_FALSE; + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_all_tests()); + TEST(CU_TRUE == f_exit_called); + test_results(1,0,0,0,0,1,0,0,0,1); + + CU_set_test_active(pTest1, CU_FALSE); + CU_set_test_active(pTest2, CU_TRUE); + CU_set_test_active(pTest3, CU_FALSE); + CU_set_test_active(pTest4, CU_TRUE); + CU_set_test_active(pTest5, CU_FALSE); + CU_set_test_active(pTest6, CU_TRUE); + CU_set_test_active(pTest7, CU_FALSE); + CU_set_test_active(pTest8, CU_TRUE); + CU_set_test_active(pTest9, CU_FALSE); + CU_set_test_active(pTest10, CU_TRUE); + f_exit_called = CU_FALSE; + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* some tests active */ + TEST(CU_TRUE == f_exit_called); + test_results(1,1,0,2,2,3,2,0,2,3); + f_exit_called = CU_FALSE; + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_all_tests()); + TEST(CU_TRUE == f_exit_called); + test_results(1,0,0,0,0,1,0,0,0,1); + + CU_set_test_active(pTest1, CU_TRUE); + CU_set_test_active(pTest2, CU_TRUE); + CU_set_test_active(pTest3, CU_TRUE); + CU_set_test_active(pTest4, CU_TRUE); + CU_set_test_active(pTest5, CU_TRUE); + CU_set_test_active(pTest6, CU_TRUE); + CU_set_test_active(pTest7, CU_TRUE); + CU_set_test_active(pTest8, CU_TRUE); + CU_set_test_active(pTest9, CU_TRUE); + CU_set_test_active(pTest10, CU_TRUE); + + f_exit_called = CU_FALSE; + CU_set_suite_initfunc(pSuite1, &suite_fail); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* change a suite init function */ + CU_set_suite_initfunc(pSuite1, NULL); + TEST(CU_TRUE == f_exit_called); + test_results(0,1,0,0,0,0,0,0,0,1); + + f_exit_called = CU_FALSE; + CU_set_suite_cleanupfunc(pSuite1, &suite_fail); + TEST(CUE_SCLEAN_FAILED == CU_run_all_tests()); /* change a suite cleanup function */ + CU_set_suite_cleanupfunc(pSuite1, NULL); + TEST(CU_TRUE == f_exit_called); + test_results(1,1,0,5,2,0,5,3,2,3); + + f_exit_called = CU_FALSE; + CU_set_test_func(pTest1, &test_fail); + CU_set_test_func(pTest3, &test_fail); + CU_set_test_func(pTest5, &test_fail); + CU_set_test_func(pTest9, &test_fail); + CU_set_test_func(pTest10, &test_fail); + TEST(CUE_SINIT_FAILED == CU_run_all_tests()); /* change a test function */ + CU_set_test_func(pTest1, &test_succeed); + CU_set_test_func(pTest3, &test_succeed); + CU_set_test_func(pTest5, &test_succeed); + CU_set_test_func(pTest9, &test_succeed); + CU_set_test_func(pTest10, &test_succeed); + TEST(CU_TRUE == f_exit_called); + test_results(1,1,0,5,5,0,5,0,5,6); + + /* clean up after testing */ + CU_set_error_action(CUEA_IGNORE); + CU_cleanup_registry(); +} + +/*-------------------------------------------------*/ +static void test_CU_run_suite(void) +{ + CU_pSuite pSuite1 = NULL; + CU_pSuite pSuite2 = NULL; + CU_pSuite pSuite3 = NULL; + CU_pSuite pSuite4 = NULL; + CU_pTest pTest1 = NULL; + CU_pTest pTest2 = NULL; + CU_pTest pTest3 = NULL; + CU_pTest pTest4 = NULL; + CU_pTest pTest5 = NULL; + CU_pTest pTest6 = NULL; + CU_pTest pTest7 = NULL; + CU_pTest pTest8 = NULL; + CU_pTest pTest9 = NULL; + + /* error - NULL suite (CUEA_IGNORE) */ + CU_set_error_action(CUEA_IGNORE); + + TEST(CUE_NOSUITE == CU_run_suite(NULL)); + TEST(CUE_NOSUITE == CU_get_error()); + + /* error - NULL suite (CUEA_FAIL) */ + CU_set_error_action(CUEA_FAIL); + + TEST(CUE_NOSUITE == CU_run_suite(NULL)); + TEST(CUE_NOSUITE == CU_get_error()); + + /* error - NULL suite (CUEA_ABORT) */ + CU_set_error_action(CUEA_ABORT); + + f_exit_called = CU_FALSE; + CU_run_suite(NULL); + TEST(CU_TRUE == f_exit_called); + f_exit_called = CU_FALSE; + + /* register some suites and tests */ + CU_initialize_registry(); + pSuite1 = CU_add_suite("suite1", NULL, NULL); + pTest1 = CU_add_test(pSuite1, "test1", test_succeed); + pTest2 = CU_add_test(pSuite1, "test2", test_fail); + pTest3 = CU_add_test(pSuite1, "test3", test_succeed); + pTest4 = CU_add_test(pSuite1, "test4", test_fail); + pTest5 = CU_add_test(pSuite1, "test5", test_succeed); + pSuite2 = CU_add_suite("suite1", suite_fail, NULL); /* duplicate suite name OK */ + pTest6 = CU_add_test(pSuite2, "test6", test_succeed); + pTest7 = CU_add_test(pSuite2, "test7", test_succeed); + pSuite3 = CU_add_suite("suite3", NULL, suite_fail); + pTest8 = CU_add_test(pSuite3, "test8", test_fail); + pTest9 = CU_add_test(pSuite3, "test8", test_succeed); /* duplicate test name OK */ + pSuite4 = CU_add_suite("suite4", NULL, NULL); + + TEST_FATAL(4 == CU_get_registry()->uiNumberOfSuites); + TEST_FATAL(9 == CU_get_registry()->uiNumberOfTests); + + /* run each suite (CUEA_IGNORE) */ + CU_set_error_action(CUEA_IGNORE); + + TEST(CUE_SUCCESS == CU_run_suite(pSuite1)); /* suites/tests active */ + test_results(1,0,0,5,2,0,5,3,2,2); + + TEST(CUE_SINIT_FAILED == CU_run_suite(pSuite2)); + test_results(0,1,0,0,0,0,0,0,0,1); + + TEST(CUE_SCLEAN_FAILED == CU_run_suite(pSuite3)); + test_results(1,1,0,2,1,0,2,1,1,2); + + TEST(CUE_SUCCESS == CU_run_suite(pSuite4)); + test_results(1,0,0,0,0,0,0,0,0,0); + + CU_set_suite_active(pSuite3, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SUCCESS == CU_run_suite(pSuite3)); /* suite inactive */ + test_results(0,0,1,0,0,0,0,0,0,0); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_SUITE_INACTIVE == CU_run_suite(pSuite3)); + test_results(0,0,1,0,0,0,0,0,0,1); + CU_set_suite_active(pSuite3, CU_TRUE); + + CU_set_test_active(pTest1, CU_FALSE); + CU_set_test_active(pTest2, CU_FALSE); + CU_set_test_active(pTest3, CU_FALSE); + CU_set_test_active(pTest4, CU_FALSE); + CU_set_test_active(pTest5, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SUCCESS == CU_run_suite(pSuite1)); /* all tests inactive */ + test_results(1,0,0,0,0,5,0,0,0,0); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_suite(pSuite1)); + test_results(1,0,0,0,0,5,0,0,0,5); + + CU_set_test_active(pTest1, CU_TRUE); + CU_set_test_active(pTest2, CU_FALSE); + CU_set_test_active(pTest3, CU_TRUE); + CU_set_test_active(pTest4, CU_FALSE); + CU_set_test_active(pTest5, CU_TRUE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SUCCESS == CU_run_suite(pSuite1)); /* some tests inactive */ + test_results(1,0,0,3,0,2,3,3,0,0); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_suite(pSuite1)); + test_results(1,0,0,3,0,2,3,3,0,2); + CU_set_test_active(pTest2, CU_TRUE); + CU_set_test_active(pTest4, CU_TRUE); + + CU_set_suite_initfunc(pSuite1, &suite_fail); + TEST(CUE_SINIT_FAILED == CU_run_suite(pSuite1)); /* change a suite init function */ + CU_set_suite_initfunc(pSuite1, NULL); + test_results(0,1,0,0,0,0,0,0,0,1); + + CU_set_suite_cleanupfunc(pSuite1, &suite_fail); + TEST(CUE_SCLEAN_FAILED == CU_run_suite(pSuite1)); /* change a suite cleanup function */ + CU_set_suite_cleanupfunc(pSuite1, NULL); + test_results(1,1,0,5,2,0,5,3,2,3); + + CU_set_test_func(pTest1, &test_fail); + CU_set_test_func(pTest3, &test_fail); + CU_set_test_func(pTest5, &test_fail); + TEST(CUE_SUCCESS == CU_run_suite(pSuite1)); /* change a test function */ + CU_set_test_func(pTest1, &test_succeed); + CU_set_test_func(pTest3, &test_succeed); + CU_set_test_func(pTest5, &test_succeed); + test_results(1,0,0,5,5,0,5,0,5,5); + + /* run each suite (CUEA_FAIL) */ + CU_set_error_action(CUEA_FAIL); + + TEST(CUE_SUCCESS == CU_run_suite(pSuite1)); /* suite active */ + test_results(1,0,0,5,2,0,5,3,2,2); + + TEST(CUE_SINIT_FAILED == CU_run_suite(pSuite2)); + test_results(0,1,0,0,0,0,0,0,0,1); + + TEST(CUE_SCLEAN_FAILED == CU_run_suite(pSuite3)); + test_results(1,1,0,2,1,0,2,1,1,2); + + TEST(CUE_SUCCESS == CU_run_suite(pSuite4)); + test_results(1,0,0,0,0,0,0,0,0,0); + + CU_set_suite_active(pSuite1, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SUCCESS == CU_run_suite(pSuite1)); /* suite inactive */ + test_results(0,0,1,0,0,0,0,0,0,0); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_SUITE_INACTIVE == CU_run_suite(pSuite1)); + test_results(0,0,1,0,0,0,0,0,0,1); + CU_set_suite_active(pSuite1, CU_TRUE); + + CU_set_test_active(pTest8, CU_FALSE); + CU_set_test_active(pTest9, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SCLEAN_FAILED == CU_run_suite(pSuite3)); /* all tests inactive */ + test_results(1,1,0,0,0,2,0,0,0,1); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_suite(pSuite3)); + test_results(1,1,0,0,0,1,0,0,0,2); + + CU_set_test_active(pTest8, CU_TRUE); + CU_set_test_active(pTest9, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SCLEAN_FAILED == CU_run_suite(pSuite3)); /* some tests inactive */ + test_results(1,1,0,1,1,1,1,0,1,2); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_suite(pSuite3)); + test_results(1,1,0,1,1,1,1,0,1,3); + CU_set_test_active(pTest9, CU_TRUE); + + CU_set_suite_initfunc(pSuite2, NULL); + TEST(CUE_SUCCESS == CU_run_suite(pSuite2)); /* change a suite init function */ + CU_set_suite_initfunc(pSuite2, &suite_fail); + test_results(1,0,0,2,0,0,2,2,0,0); + + CU_set_suite_cleanupfunc(pSuite1, &suite_fail); + TEST(CUE_SCLEAN_FAILED == CU_run_suite(pSuite1)); /* change a suite cleanup function */ + CU_set_suite_cleanupfunc(pSuite1, NULL); + test_results(1,1,0,5,2,0,5,3,2,3); + + CU_set_test_func(pTest2, &test_succeed); + CU_set_test_func(pTest4, &test_succeed); + TEST(CUE_SUCCESS == CU_run_suite(pSuite1)); /* change a test function */ + CU_set_test_func(pTest2, &test_fail); + CU_set_test_func(pTest4, &test_fail); + test_results(1,0,0,5,0,0,5,5,0,0); + + /* run each suite (CUEA_ABORT) */ + CU_set_error_action(CUEA_ABORT); + + f_exit_called = CU_FALSE; + TEST(CUE_SUCCESS == CU_run_suite(pSuite1)); /* suite active */ + TEST(CU_FALSE == f_exit_called); + test_results(1,0,0,5,2,0,5,3,2,2); + + f_exit_called = CU_FALSE; + TEST(CUE_SINIT_FAILED == CU_run_suite(pSuite2)); + TEST(CU_TRUE == f_exit_called); + f_exit_called = CU_FALSE; + test_results(0,1,0,0,0,0,0,0,0,1); + + f_exit_called = CU_FALSE; + TEST(CUE_SCLEAN_FAILED == CU_run_suite(pSuite3)); + TEST(CU_TRUE == f_exit_called); + test_results(1,1,0,2,1,0,2,1,1,2); + + f_exit_called = CU_FALSE; + TEST(CUE_SUCCESS == CU_run_suite(pSuite4)); + TEST(CU_FALSE == f_exit_called); + test_results(1,0,0,0,0,0,0,0,0,0); + + CU_set_suite_active(pSuite2, CU_FALSE); + f_exit_called = CU_FALSE; + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SUCCESS == CU_run_suite(pSuite2)); /* suite inactive, but not a failure */ + TEST(CU_FALSE == f_exit_called); + test_results(0,0,1,0,0,0,0,0,0,0); + f_exit_called = CU_FALSE; + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_SUITE_INACTIVE == CU_run_suite(pSuite2)); + TEST(CU_TRUE == f_exit_called); + test_results(0,0,1,0,0,0,0,0,0,1); + CU_set_suite_active(pSuite2, CU_TRUE); + + CU_set_test_active(pTest8, CU_FALSE); + CU_set_test_active(pTest9, CU_FALSE); + f_exit_called = CU_FALSE; + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SCLEAN_FAILED == CU_run_suite(pSuite3)); /* all tests inactive */ + TEST(CU_TRUE == f_exit_called); + test_results(1,1,0,0,0,2,0,0,0,1); + f_exit_called = CU_FALSE; + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_suite(pSuite3)); + TEST(CU_TRUE == f_exit_called); + test_results(1,1,0,0,0,1,0,0,0,2); + + CU_set_test_active(pTest8, CU_FALSE); + CU_set_test_active(pTest9, CU_TRUE); + f_exit_called = CU_FALSE; + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SCLEAN_FAILED == CU_run_suite(pSuite3)); /* some tests inactive */ + TEST(CU_TRUE == f_exit_called); + test_results(1,1,0,1,0,1,1,1,0,1); + f_exit_called = CU_FALSE; + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_suite(pSuite3)); + TEST(CU_TRUE == f_exit_called); + test_results(1,1,0,0,0,1,0,0,0,2); + CU_set_test_active(pTest8, CU_TRUE); + + f_exit_called = CU_FALSE; + CU_set_suite_initfunc(pSuite1, &suite_fail); + TEST(CUE_SINIT_FAILED == CU_run_suite(pSuite1)); /* change a suite init function */ + CU_set_suite_initfunc(pSuite1, NULL); + TEST(CU_TRUE == f_exit_called); + test_results(0,1,0,0,0,0,0,0,0,1); + + f_exit_called = CU_FALSE; + CU_set_suite_cleanupfunc(pSuite1, &suite_fail); + TEST(CUE_SCLEAN_FAILED == CU_run_suite(pSuite1)); /* change a suite cleanup function */ + CU_set_suite_cleanupfunc(pSuite1, NULL); + TEST(CU_TRUE == f_exit_called); + test_results(1,1,0,5,2,0,5,3,2,3); + + f_exit_called = CU_FALSE; + CU_set_test_func(pTest8, &test_succeed); + CU_set_test_func(pTest9, &test_fail); + TEST(CUE_SCLEAN_FAILED == CU_run_suite(pSuite3)); /* change a test function */ + CU_set_test_func(pTest8, &test_fail); + CU_set_test_func(pTest9, &test_succeed); + TEST(CU_TRUE == f_exit_called); + test_results(1,1,0,2,1,0,2,1,1,2); + + /* clean up after testing */ + CU_set_error_action(CUEA_IGNORE); + CU_cleanup_registry(); +} + +/*-------------------------------------------------*/ +static void test_CU_run_test(void) +{ + CU_pSuite pSuite1 = NULL; + CU_pSuite pSuite2 = NULL; + CU_pSuite pSuite3 = NULL; + CU_pTest pTest1 = NULL; + CU_pTest pTest2 = NULL; + CU_pTest pTest3 = NULL; + CU_pTest pTest4 = NULL; + CU_pTest pTest5 = NULL; + CU_pTest pTest6 = NULL; + CU_pTest pTest7 = NULL; + CU_pTest pTest8 = NULL; + CU_pTest pTest9 = NULL; + + /* register some suites and tests */ + CU_initialize_registry(); + pSuite1 = CU_add_suite("suite1", NULL, NULL); + pTest1 = CU_add_test(pSuite1, "test1", test_succeed); + pTest2 = CU_add_test(pSuite1, "test2", test_fail); + pTest3 = CU_add_test(pSuite1, "test3", test_succeed); + pTest4 = CU_add_test(pSuite1, "test4", test_fail); + pTest5 = CU_add_test(pSuite1, "test5", test_succeed); + pSuite2 = CU_add_suite("suite2", suite_fail, NULL); + pTest6 = CU_add_test(pSuite2, "test6", test_succeed); + pTest7 = CU_add_test(pSuite2, "test7", test_succeed); + pSuite3 = CU_add_suite("suite2", NULL, suite_fail); /* duplicate suite name OK */ + pTest8 = CU_add_test(pSuite3, "test8", test_fail); + pTest9 = CU_add_test(pSuite3, "test8", test_succeed); /* duplicate test name OK */ + + TEST_FATAL(3 == CU_get_registry()->uiNumberOfSuites); + TEST_FATAL(9 == CU_get_registry()->uiNumberOfTests); + + /* error - NULL suite (CUEA_IGNORE) */ + CU_set_error_action(CUEA_IGNORE); + + TEST(CUE_NOSUITE == CU_run_test(NULL, pTest1)); + TEST(CUE_NOSUITE == CU_get_error()); + + /* error - NULL suite (CUEA_FAIL) */ + CU_set_error_action(CUEA_FAIL); + + TEST(CUE_NOSUITE == CU_run_test(NULL, pTest1)); + TEST(CUE_NOSUITE == CU_get_error()); + + /* error - NULL test (CUEA_ABORT) */ + CU_set_error_action(CUEA_ABORT); + + f_exit_called = CU_FALSE; + CU_run_test(NULL, pTest1); + TEST(CU_TRUE == f_exit_called); + f_exit_called = CU_FALSE; + + /* error - NULL test (CUEA_IGNORE) */ + CU_set_error_action(CUEA_IGNORE); + + TEST(CUE_NOTEST == CU_run_test(pSuite1, NULL)); + TEST(CUE_NOTEST == CU_get_error()); + + /* error - NULL test (CUEA_FAIL) */ + CU_set_error_action(CUEA_FAIL); + + TEST(CUE_NOTEST == CU_run_test(pSuite1, NULL)); + TEST(CUE_NOTEST == CU_get_error()); + + /* error - NULL test (CUEA_ABORT) */ + CU_set_error_action(CUEA_ABORT); + + f_exit_called = CU_FALSE; + CU_run_test(pSuite1, NULL); + TEST(CU_TRUE == f_exit_called); + f_exit_called = CU_FALSE; + + /* error - test not in suite (CUEA_IGNORE) */ + CU_set_error_action(CUEA_IGNORE); + + TEST(CUE_TEST_NOT_IN_SUITE == CU_run_test(pSuite3, pTest1)); + TEST(CUE_TEST_NOT_IN_SUITE == CU_get_error()); + + /* error - NULL test (CUEA_FAIL) */ + CU_set_error_action(CUEA_FAIL); + + TEST(CUE_TEST_NOT_IN_SUITE == CU_run_test(pSuite3, pTest1)); + TEST(CUE_TEST_NOT_IN_SUITE == CU_get_error()); + + /* error - NULL test (CUEA_ABORT) */ + CU_set_error_action(CUEA_ABORT); + + f_exit_called = CU_FALSE; + CU_run_test(pSuite3, pTest1); + TEST(CU_TRUE == f_exit_called); + f_exit_called = CU_FALSE; + + /* run each test (CUEA_IGNORE) */ + CU_set_error_action(CUEA_IGNORE); + + TEST(CUE_SUCCESS == CU_run_test(pSuite1, pTest1)); /* all suite/tests active */ + test_results(0,0,0,1,0,0,1,1,0,0); + + TEST(CUE_SUCCESS == CU_run_test(pSuite1, pTest2)); + test_results(0,0,0,1,1,0,1,0,1,1); + + TEST(CUE_SUCCESS == CU_run_test(pSuite1, pTest3)); + test_results(0,0,0,1,0,0,1,1,0,0); + + TEST(CUE_SUCCESS == CU_run_test(pSuite1, pTest4)); + test_results(0,0,0,1,1,0,1,0,1,1); + + TEST(CUE_SUCCESS == CU_run_test(pSuite1, pTest5)); + test_results(0,0,0,1,0,0,1,1,0,0); + + TEST(CUE_SINIT_FAILED == CU_run_test(pSuite2, pTest6)); + test_results(0,1,0,0,0,0,0,0,0,1); + + TEST(CUE_SINIT_FAILED == CU_run_test(pSuite2, pTest7)); + test_results(0,1,0,0,0,0,0,0,0,1); + + TEST(CUE_SCLEAN_FAILED == CU_run_test(pSuite3, pTest8)); + test_results(0,1,0,1,1,0,1,0,1,2); + + TEST(CUE_SCLEAN_FAILED == CU_run_test(pSuite3, pTest9)); + test_results(0,1,0,1,0,0,1,1,0,1); + + CU_set_suite_active(pSuite1, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SUITE_INACTIVE == CU_run_test(pSuite1, pTest1)); /* suite inactive */ + test_results(0,0,1,0,0,0,0,0,0,0); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_SUITE_INACTIVE == CU_run_test(pSuite1, pTest1)); + test_results(0,0,1,0,0,0,0,0,0,1); + CU_set_suite_active(pSuite1, CU_TRUE); + + CU_set_test_active(pTest1, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_TEST_INACTIVE == CU_run_test(pSuite1, pTest1)); /* test inactive */ + test_results(0,0,0,0,0,1,0,0,0,0); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_TEST_INACTIVE == CU_run_test(pSuite1, pTest1)); + test_results(0,0,0,0,1,1,0,0,0,1); + CU_set_test_active(pTest1, CU_TRUE); + + CU_set_suite_initfunc(pSuite1, &suite_fail); + TEST(CUE_SINIT_FAILED == CU_run_test(pSuite1, pTest1)); /* change a suite init function */ + CU_set_suite_initfunc(pSuite1, NULL); + test_results(0,1,0,0,0,0,0,0,0,1); + + CU_set_suite_cleanupfunc(pSuite1, &suite_fail); + TEST(CUE_SCLEAN_FAILED == CU_run_test(pSuite1, pTest1)); /* change a suite cleanup function */ + CU_set_suite_cleanupfunc(pSuite1, NULL); + test_results(0,1,0,1,0,0,1,1,0,1); + + CU_set_test_func(pTest8, &test_succeed); + TEST(CUE_SCLEAN_FAILED == CU_run_test(pSuite3, pTest8)); /* change a test function */ + CU_set_test_func(pTest8, &test_fail); + test_results(0,1,0,1,0,0,1,1,0,1); + + /* run each test (CUEA_FAIL) */ + CU_set_error_action(CUEA_FAIL); + + TEST(CUE_SUCCESS == CU_run_test(pSuite1, pTest1)); /* suite/test active */ + test_results(0,0,0,1,0,0,1,1,0,0); + + TEST(CUE_SUCCESS == CU_run_test(pSuite1, pTest2)); + test_results(0,0,0,1,1,0,1,0,1,1); + + TEST(CUE_SUCCESS == CU_run_test(pSuite1, pTest3)); + test_results(0,0,0,1,0,0,1,1,0,0); + + TEST(CUE_SUCCESS == CU_run_test(pSuite1, pTest4)); + test_results(0,0,0,1,1,0,1,0,1,1); + + TEST(CUE_SUCCESS == CU_run_test(pSuite1, pTest5)); + test_results(0,0,0,1,0,0,1,1,0,0); + + TEST(CUE_SINIT_FAILED == CU_run_test(pSuite2, pTest6)); + test_results(0,1,0,0,0,0,0,0,0,1); + + TEST(CUE_SINIT_FAILED == CU_run_test(pSuite2, pTest7)); + test_results(0,1,0,0,0,0,0,0,0,1); + + TEST(CUE_SCLEAN_FAILED == CU_run_test(pSuite3, pTest8)); + test_results(0,1,0,1,1,0,1,0,1,2); + + TEST(CUE_SCLEAN_FAILED == CU_run_test(pSuite3, pTest9)); + test_results(0,1,0,1,0,0,1,1,0,1); + + CU_set_suite_active(pSuite2, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SUITE_INACTIVE == CU_run_test(pSuite2, pTest7)); /* suite inactive */ + test_results(0,0,1,0,0,0,0,0,0,0); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_SUITE_INACTIVE == CU_run_test(pSuite2, pTest7)); + test_results(0,0,1,0,0,0,0,0,0,1); + CU_set_suite_active(pSuite2, CU_TRUE); + + CU_set_test_active(pTest7, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + TEST(CUE_SINIT_FAILED == CU_run_test(pSuite2, pTest7)); /* test inactive */ + test_results(0,1,0,0,0,0,0,0,0,1); + CU_set_fail_on_inactive(CU_TRUE); + TEST(CUE_SINIT_FAILED == CU_run_test(pSuite2, pTest7)); + test_results(0,1,0,0,0,0,0,0,0,1); + CU_set_test_active(pTest7, CU_TRUE); + + CU_set_suite_initfunc(pSuite2, NULL); + TEST(CUE_SUCCESS == CU_run_test(pSuite2, pTest6)); /* change a suite init function */ + CU_set_suite_initfunc(pSuite2, &suite_fail); + test_results(0,0,0,1,0,0,1,1,0,0); + + CU_set_suite_cleanupfunc(pSuite3, NULL); + TEST(CUE_SUCCESS == CU_run_test(pSuite3, pTest8)); /* change a suite cleanup function */ + CU_set_suite_cleanupfunc(pSuite3, &suite_fail); + test_results(0,0,0,1,1,0,1,0,1,1); + + CU_set_test_func(pTest8, &test_succeed); + TEST(CUE_SCLEAN_FAILED == CU_run_test(pSuite3, pTest8)); /* change a test function */ + CU_set_test_func(pTest8, &test_fail); + test_results(0,1,0,1,0,0,1,1,0,1); + + /* run each test (CUEA_ABORT) */ + CU_set_error_action(CUEA_ABORT); + + f_exit_called = CU_FALSE; + TEST(CUE_SUCCESS == CU_run_test(pSuite1, pTest1)); + TEST(CU_FALSE == f_exit_called); + test_results(0,0,0,1,0,0,1,1,0,0); + + f_exit_called = CU_FALSE; + TEST(CUE_SUCCESS == CU_run_test(pSuite1, pTest2)); + TEST(CU_FALSE == f_exit_called); + test_results(0,0,0,1,1,0,1,0,1,1); + + f_exit_called = CU_FALSE; + TEST(CUE_SUCCESS == CU_run_test(pSuite1, pTest3)); + TEST(CU_FALSE == f_exit_called); + test_results(0,0,0,1,0,0,1,1,0,0); + + f_exit_called = CU_FALSE; + TEST(CUE_SUCCESS == CU_run_test(pSuite1, pTest4)); + TEST(CU_FALSE == f_exit_called); + test_results(0,0,0,1,1,0,1,0,1,1); + + f_exit_called = CU_FALSE; + TEST(CUE_SUCCESS == CU_run_test(pSuite1, pTest5)); + TEST(CU_FALSE == f_exit_called); + test_results(0,0,0,1,0,0,1,1,0,0); + + f_exit_called = CU_FALSE; + TEST(CUE_SINIT_FAILED == CU_run_test(pSuite2, pTest6)); + TEST(CU_TRUE == f_exit_called); + test_results(0,1,0,0,0,0,0,0,0,1); + + f_exit_called = CU_FALSE; + TEST(CUE_SINIT_FAILED == CU_run_test(pSuite2, pTest7)); + TEST(CU_TRUE == f_exit_called); + test_results(0,1,0,0,0,0,0,0,0,1); + + f_exit_called = CU_FALSE; + TEST(CUE_SCLEAN_FAILED == CU_run_test(pSuite3, pTest8)); + TEST(CU_TRUE == f_exit_called); + test_results(0,1,0,1,1,0,1,0,1,2); + + f_exit_called = CU_FALSE; + TEST(CUE_SCLEAN_FAILED == CU_run_test(pSuite3, pTest9)); + TEST(CU_TRUE == f_exit_called); + test_results(0,1,0,1,0,0,1,1,0,1); + + CU_set_suite_active(pSuite2, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + f_exit_called = CU_FALSE; + TEST(CUE_SUITE_INACTIVE == CU_run_test(pSuite2, pTest6)); /* suite inactive */ + TEST(CU_TRUE == f_exit_called); + test_results(0,0,1,0,0,0,0,0,0,0); + CU_set_fail_on_inactive(CU_TRUE); + f_exit_called = CU_FALSE; + TEST(CUE_SUITE_INACTIVE == CU_run_test(pSuite2, pTest6)); + TEST(CU_TRUE == f_exit_called); + test_results(0,0,1,0,0,0,0,0,0,1); + CU_set_suite_active(pSuite2, CU_TRUE); + + CU_set_test_active(pTest6, CU_FALSE); + CU_set_fail_on_inactive(CU_FALSE); + f_exit_called = CU_FALSE; + TEST(CUE_SINIT_FAILED == CU_run_test(pSuite2, pTest6)); /* test inactive */ + TEST(CU_TRUE == f_exit_called); + test_results(0,1,0,0,0,0,0,0,0,1); + CU_set_fail_on_inactive(CU_TRUE); + f_exit_called = CU_FALSE; + TEST(CUE_SINIT_FAILED == CU_run_test(pSuite2, pTest6)); + TEST(CU_TRUE == f_exit_called); + test_results(0,1,0,0,0,0,0,0,0,1); + CU_set_test_active(pTest6, CU_TRUE); + + f_exit_called = CU_FALSE; + CU_set_suite_initfunc(pSuite2, NULL); + TEST(CUE_SUCCESS == CU_run_test(pSuite2, pTest6)); /* change a suite init function */ + CU_set_suite_initfunc(pSuite2, &suite_fail); + TEST(CU_FALSE == f_exit_called); + test_results(0,0,0,1,0,0,1,1,0,0); + + f_exit_called = CU_FALSE; + CU_set_suite_cleanupfunc(pSuite1, &suite_fail); + TEST(CUE_SCLEAN_FAILED == CU_run_test(pSuite1, pTest1)); /* change a suite cleanup function */ + CU_set_suite_cleanupfunc(pSuite1, NULL); + TEST(CU_TRUE == f_exit_called); + test_results(0,1,0,1,0,0,1,1,0,1); + + f_exit_called = CU_FALSE; + CU_set_test_func(pTest8, &test_succeed); + TEST(CUE_SCLEAN_FAILED == CU_run_test(pSuite3, pTest8)); /* change a test function */ + CU_set_test_func(pTest8, &test_fail); + TEST(CU_TRUE == f_exit_called); + test_results(0,1,0,1,0,0,1,1,0,1); + + /* clean up after testing */ + CU_set_error_action(CUEA_IGNORE); + CU_cleanup_registry(); +} + +/*-------------------------------------------------*/ +/* tests CU_assertImplementation() + * CU_get_failure_list() + * CU_clear_previous_results() + */ +static void test_CU_assertImplementation(void) +{ + CU_Test dummy_test; + CU_Suite dummy_suite; + CU_pFailureRecord pFailure1 = NULL; + CU_pFailureRecord pFailure2 = NULL; + CU_pFailureRecord pFailure3 = NULL; + CU_pFailureRecord pFailure4 = NULL; + CU_pFailureRecord pFailure5 = NULL; + CU_pFailureRecord pFailure6 = NULL; + + CU_clear_previous_results(); + + TEST(NULL == CU_get_failure_list()); + TEST(0 == CU_get_number_of_asserts()); + TEST(0 == CU_get_number_of_failures()); + TEST(0 == CU_get_number_of_failure_records()); + + /* fool CU_assertImplementation into thinking test run is in progress */ + f_pCurTest = &dummy_test; + f_pCurSuite = &dummy_suite; + + /* asserted value is CU_TRUE*/ + TEST(CU_TRUE == CU_assertImplementation(CU_TRUE, 100, "Nothing happened 0.", "dummy0.c", "dummy_func0", CU_FALSE)); + + TEST(NULL == CU_get_failure_list()); + TEST(1 == CU_get_number_of_asserts()); + TEST(0 == CU_get_number_of_failures()); + TEST(0 == CU_get_number_of_failure_records()); + + TEST(CU_TRUE == CU_assertImplementation(CU_TRUE, 101, "Nothing happened 1.", "dummy1.c", "dummy_func1", CU_FALSE)); + + TEST(NULL == CU_get_failure_list()); + TEST(2 == CU_get_number_of_asserts()); + TEST(0 == CU_get_number_of_failures()); + TEST(0 == CU_get_number_of_failure_records()); + + /* asserted value is CU_FALSE */ + TEST(CU_FALSE == CU_assertImplementation(CU_FALSE, 102, "Something happened 2.", "dummy2.c", "dummy_func2", CU_FALSE)); + + TEST(NULL != CU_get_failure_list()); + TEST(3 == CU_get_number_of_asserts()); + TEST(1 == CU_get_number_of_failures()); + TEST(1 == CU_get_number_of_failure_records()); + + TEST(CU_FALSE == CU_assertImplementation(CU_FALSE, 103, "Something happened 3.", "dummy3.c", "dummy_func3", CU_FALSE)); + + TEST(NULL != CU_get_failure_list()); + TEST(4 == CU_get_number_of_asserts()); + TEST(2 == CU_get_number_of_failures()); + TEST(2 == CU_get_number_of_failure_records()); + + TEST(CU_FALSE == CU_assertImplementation(CU_FALSE, 104, "Something happened 4.", "dummy4.c", "dummy_func4", CU_FALSE)); + + TEST(NULL != CU_get_failure_list()); + TEST(5 == CU_get_number_of_asserts()); + TEST(3 == CU_get_number_of_failures()); + TEST(3 == CU_get_number_of_failure_records()); + + if (3 == CU_get_number_of_failure_records()) { + pFailure1 = CU_get_failure_list(); + TEST(102 == pFailure1->uiLineNumber); + TEST(!strcmp("dummy2.c", pFailure1->strFileName)); + TEST(!strcmp("Something happened 2.", pFailure1->strCondition)); + TEST(&dummy_test == pFailure1->pTest); + TEST(&dummy_suite == pFailure1->pSuite); + TEST(NULL != pFailure1->pNext); + TEST(NULL == pFailure1->pPrev); + + pFailure2 = pFailure1->pNext; + TEST(103 == pFailure2->uiLineNumber); + TEST(!strcmp("dummy3.c", pFailure2->strFileName)); + TEST(!strcmp("Something happened 3.", pFailure2->strCondition)); + TEST(&dummy_test == pFailure2->pTest); + TEST(&dummy_suite == pFailure2->pSuite); + TEST(NULL != pFailure2->pNext); + TEST(pFailure1 == pFailure2->pPrev); + + pFailure3 = pFailure2->pNext; + TEST(104 == pFailure3->uiLineNumber); + TEST(!strcmp("dummy4.c", pFailure3->strFileName)); + TEST(!strcmp("Something happened 4.", pFailure3->strCondition)); + TEST(&dummy_test == pFailure3->pTest); + TEST(&dummy_suite == pFailure3->pSuite); + TEST(NULL == pFailure3->pNext); + TEST(pFailure2 == pFailure3->pPrev); + } + else + FAIL("Unexpected number of failure records."); + + /* confirm destruction of failure records */ + pFailure4 = pFailure1; + pFailure5 = pFailure2; + pFailure6 = pFailure3; + TEST(0 != test_cunit_get_n_memevents(pFailure4)); + TEST(test_cunit_get_n_allocations(pFailure4) != test_cunit_get_n_deallocations(pFailure4)); + TEST(0 != test_cunit_get_n_memevents(pFailure5)); + TEST(test_cunit_get_n_allocations(pFailure5) != test_cunit_get_n_deallocations(pFailure5)); + TEST(0 != test_cunit_get_n_memevents(pFailure6)); + TEST(test_cunit_get_n_allocations(pFailure6) != test_cunit_get_n_deallocations(pFailure6)); + + CU_clear_previous_results(); + TEST(0 != test_cunit_get_n_memevents(pFailure4)); + TEST(test_cunit_get_n_allocations(pFailure4) == test_cunit_get_n_deallocations(pFailure4)); + TEST(0 != test_cunit_get_n_memevents(pFailure5)); + TEST(test_cunit_get_n_allocations(pFailure5) == test_cunit_get_n_deallocations(pFailure5)); + TEST(0 != test_cunit_get_n_memevents(pFailure6)); + TEST(test_cunit_get_n_allocations(pFailure6) == test_cunit_get_n_deallocations(pFailure6)); + TEST(0 == CU_get_number_of_asserts()); + TEST(0 == CU_get_number_of_successes()); + TEST(0 == CU_get_number_of_failures()); + TEST(0 == CU_get_number_of_failure_records()); + + f_pCurTest = NULL; + f_pCurSuite = NULL; +} + +/*-------------------------------------------------*/ +static void test_add_failure(void) +{ + CU_Test test1; + CU_Suite suite1; + CU_pFailureRecord pFailure1 = NULL; + CU_pFailureRecord pFailure2 = NULL; + CU_pFailureRecord pFailure3 = NULL; + CU_pFailureRecord pFailure4 = NULL; + CU_RunSummary run_summary = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + /* test under memory exhaustion */ + test_cunit_deactivate_malloc(); + add_failure(&pFailure1, &run_summary, CUF_AssertFailed, 100, "condition 0", "file0.c", &suite1, &test1); + TEST(NULL == pFailure1); + TEST(0 == run_summary.nFailureRecords); + test_cunit_activate_malloc(); + + /* normal operation */ + add_failure(&pFailure1, &run_summary, CUF_AssertFailed, 101, "condition 1", "file1.c", &suite1, &test1); + TEST(1 == run_summary.nFailureRecords); + if (TEST(NULL != pFailure1)) { + TEST(101 == pFailure1->uiLineNumber); + TEST(!strcmp("condition 1", pFailure1->strCondition)); + TEST(!strcmp("file1.c", pFailure1->strFileName)); + TEST(&test1 == pFailure1->pTest); + TEST(&suite1 == pFailure1->pSuite); + TEST(NULL == pFailure1->pNext); + TEST(NULL == pFailure1->pPrev); + TEST(pFailure1 == f_last_failure); + TEST(0 != test_cunit_get_n_memevents(pFailure1)); + TEST(test_cunit_get_n_allocations(pFailure1) != test_cunit_get_n_deallocations(pFailure1)); + } + + add_failure(&pFailure1, &run_summary, CUF_AssertFailed, 102, "condition 2", "file2.c", NULL, &test1); + TEST(2 == run_summary.nFailureRecords); + if (TEST(NULL != pFailure1)) { + TEST(101 == pFailure1->uiLineNumber); + TEST(!strcmp("condition 1", pFailure1->strCondition)); + TEST(!strcmp("file1.c", pFailure1->strFileName)); + TEST(&test1 == pFailure1->pTest); + TEST(&suite1 == pFailure1->pSuite); + TEST(NULL != pFailure1->pNext); + TEST(NULL == pFailure1->pPrev); + TEST(pFailure1 != f_last_failure); + TEST(0 != test_cunit_get_n_memevents(pFailure1)); + TEST(test_cunit_get_n_allocations(pFailure1) != test_cunit_get_n_deallocations(pFailure1)); + + if (TEST(NULL != (pFailure2 = pFailure1->pNext))) { + TEST(102 == pFailure2->uiLineNumber); + TEST(!strcmp("condition 2", pFailure2->strCondition)); + TEST(!strcmp("file2.c", pFailure2->strFileName)); + TEST(&test1 == pFailure2->pTest); + TEST(NULL == pFailure2->pSuite); + TEST(NULL == pFailure2->pNext); + TEST(pFailure1 == pFailure2->pPrev); + TEST(pFailure2 == f_last_failure); + TEST(0 != test_cunit_get_n_memevents(pFailure2)); + TEST(test_cunit_get_n_allocations(pFailure2) != test_cunit_get_n_deallocations(pFailure2)); + } + } + + pFailure3 = pFailure1; + pFailure4 = pFailure2; + clear_previous_results(&run_summary, &pFailure1); + + TEST(0 == run_summary.nFailureRecords); + TEST(0 != test_cunit_get_n_memevents(pFailure3)); + TEST(test_cunit_get_n_allocations(pFailure3) == test_cunit_get_n_deallocations(pFailure3)); + TEST(0 != test_cunit_get_n_memevents(pFailure4)); + TEST(test_cunit_get_n_allocations(pFailure4) == test_cunit_get_n_deallocations(pFailure4)); +} + +/*-------------------------------------------------*/ +void test_cunit_TestRun(void) +{ + test_cunit_start_tests("TestRun.c"); + + test_message_handlers(); + test_CU_fail_on_inactive(); + test_CU_run_all_tests(); + test_CU_run_suite(); + test_CU_run_test(); + test_CU_assertImplementation(); + test_add_failure(); + + test_cunit_end_tests(); +} + +#endif /* CUNIT_BUILD_TESTS */ diff --git a/pde-test-host/pde-test-host/cunit/Util.c b/pde-test-host/pde-test-host/cunit/Util.c new file mode 100755 index 0000000..8e21922 --- /dev/null +++ b/pde-test-host/pde-test-host/cunit/Util.c @@ -0,0 +1,609 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2001 Anil Kumar + * Copyright (C) 2004-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 + */ + +/* + * Generic (internal) utility functions used across CUnit. + * These were originally distributed across the other CUnit + * source files, but were consolidated here for consistency. + * + * 13/Oct/2001 Initial implementation (AK) + * + * 26/Jul/2003 Added a function to convert a string containing special + * characters into escaped character for XML/HTML usage. (AK) + * + * 16-Jul-2004 New interface, doxygen comments. (JDS) + * + * 17-Apr-2006 Added CU_translated_strlen() and CU_number_width(). + * Fixed off-by-1 error in CU_translate_special_characters(), + * modifying implementation & results in some cases. User can + * now tell if conversion failed. (JDS) + */ + +/** @file + * Utility functions (implementation). + */ +/** @addtogroup Framework + @{ +*/ + +#include +#include +#include +#include +#include + +#include "CUnit.h" +#include "TestDB.h" +#include "Util.h" + + +/*------------------------------------------------------------------------*/ +/** + * Structure containing mappings of special characters to xml entity codes. + * special_char's in the CU_bindings array will be translated during calls + * to CU_translate_special_characters(). Add additional chars/replacements + * or modify existing ones to change the behavior upon translation. + */ +static const struct bindings { + const char special_char; /**< Special character. */ + const char *replacement; /**< Entity code for special character. */ +} CU_bindings [] = { + {'&', "&"}, + {'>', ">"}, + {'<', "<"} +}; + +/*------------------------------------------------------------------------*/ +/** + * Checks whether a character is a special xml character. + * This function performs a lookup of the specified character in + * the CU_bindings structure. If it is a special character, its + * index into the CU_bindings array is returned. If not, -1 is returned. + * + * @param ch The character to check + * @return Index into CU_bindings if a special character, -1 otherwise. + */ +static int get_index(const char ch) +{ + int length = sizeof(CU_bindings)/sizeof(CU_bindings[0]); + int counter; + + for (counter = 0; counter < length && CU_bindings[counter].special_char != ch; ++counter) { + ; + } + + return (counter < length ? counter : -1); +} + +size_t CU_translate_special_characters(const char *szSrc, char *szDest, size_t maxlen) +{ +/* old implementation + size_t count = 0; + size_t src = 0; + size_t dest = 0; + size_t length = 0; + int conv_index; + + assert(NULL != szSrc); + assert(NULL != szDest); + + length = strlen(szSrc); + memset(szDest, 0, maxlen); + while ((dest < maxlen) && (src < length)) { + + if ((-1 != (conv_index = get_index(szSrc[src]))) && + ((dest + strlen(CU_bindings[conv_index].replacement)) < maxlen)) { + strcat(szDest, CU_bindings[conv_index].replacement); + dest += strlen(CU_bindings[conv_index].replacement); + ++count; + } else { + szDest[dest++] = szSrc[src]; + } + + ++src; + } + + return count; +*/ + size_t count = 0; + size_t repl_len; + int conv_index; + char *dest_start = szDest; + + assert(NULL != szSrc); + assert(NULL != szDest); + + /* only process if destination buffer not 0-length */ + if (maxlen > 0) { + + while ((maxlen > 0) && (*szSrc != '\0')) { + conv_index = get_index(*szSrc); + if (-1 != conv_index) { + if (maxlen > (repl_len = strlen(CU_bindings[conv_index].replacement))) { + memcpy(szDest, CU_bindings[conv_index].replacement, repl_len); + szDest += repl_len; + maxlen -= repl_len; + ++count; + } else { + maxlen = 0; /* ran out of room - abort conversion */ + break; + } + } else { + *szDest++ = *szSrc; + --maxlen; + } + ++szSrc; + } + + if (0 == maxlen) { + *dest_start = '\0'; /* ran out of room - return empty string in szDest */ + count = 0; + } else { + *szDest = '\0'; /* had room - make sure szDest has a terminating \0 */ + } + } + return count; +} + +/*------------------------------------------------------------------------*/ +size_t CU_translated_strlen(const char* szSrc) +{ + size_t count = 0; + int conv_index; + + assert(NULL != szSrc); + + while (*szSrc != '\0') { + if (-1 != (conv_index = get_index(*szSrc))) { + count += strlen(CU_bindings[conv_index].replacement); + } else { + ++count; + } + ++szSrc; + } + return count; +} + +/*------------------------------------------------------------------------*/ +int CU_compare_strings(const char* szSrc, const char* szDest) +{ + assert(NULL != szSrc); + assert(NULL != szDest); + + while (('\0' != *szSrc) && ('\0' != *szDest) && (toupper(*szSrc) == toupper(*szDest))) { + szSrc++; + szDest++; + } + + return (int)(*szSrc - *szDest); +} + +/*------------------------------------------------------------------------*/ +void CU_trim(char* szString) +{ + CU_trim_left(szString); + CU_trim_right(szString); +} + +/*------------------------------------------------------------------------*/ +void CU_trim_left(char* szString) +{ + int nOffset = 0; + char* szSrc = szString; + char* szDest = szString; + + assert(NULL != szString); + + /* Scan for the spaces in the starting of string. */ + for (; '\0' != *szSrc; szSrc++, nOffset++) { + if (!isspace(*szSrc)) { + break; + } + } + + for(; (0 != nOffset) && ('\0' != (*szDest = *szSrc)); szSrc++, szDest++) { + ; + } +} + +/*------------------------------------------------------------------------*/ +void CU_trim_right(char* szString) +{ + size_t nLength; + char* szSrc = szString; + + assert(NULL != szString); + nLength = strlen(szString); + /* + * Scan for specs in the end of string. + */ + for (; (0 != nLength) && isspace(*(szSrc + nLength - 1)); nLength--) { + ; + } + + *(szSrc + nLength) = '\0'; +} + +/*------------------------------------------------------------------------*/ +size_t CU_number_width(int number) +{ + char buf[33]; + + snprintf(buf, 33, "%d", number); + buf[32] = '\0'; + return (strlen(buf)); +} + +/** @} */ + +#ifdef CUNIT_BUILD_TESTS +#include "test_cunit.h" + +/* Keep BUF_LEN even or trouble ensues below... */ +#define BUF_LEN 1000 +#define MAX_LEN BUF_LEN/2 + +static void test_CU_translate_special_characters(void) +{ + char dest_buf[BUF_LEN]; + char *dest = dest_buf + MAX_LEN; + char ref_buf[BUF_LEN]; + const int mask_char = 0x01; /* char written to buffer */ + + /* set up reference buffer for testing of translated strings */ + memset(ref_buf, mask_char, BUF_LEN); + + /* empty src */ + memset(dest_buf, mask_char, BUF_LEN); + TEST(0 == CU_translate_special_characters("", dest, MAX_LEN)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "\0", 1)); + TEST(!strncmp((dest+1), ref_buf, MAX_LEN-1)); + + /* 1 char src */ + memset(dest_buf, mask_char, BUF_LEN); + TEST(0 == CU_translate_special_characters("#", dest, 0)); + TEST(!strncmp(dest_buf, ref_buf, BUF_LEN)); + + memset(dest_buf, mask_char, BUF_LEN); + TEST(0 == CU_translate_special_characters("#", dest, 1)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "\0", 1)); + TEST(!strncmp((dest+1), ref_buf, MAX_LEN-1)); + + memset(dest_buf, mask_char, BUF_LEN); + TEST(0 == CU_translate_special_characters("&", dest, 2)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "\0", 1)); + TEST(!strncmp((dest+2), ref_buf, MAX_LEN-2)); + + memset(dest_buf, mask_char, BUF_LEN); + TEST(0 == CU_translate_special_characters("&", dest, 4)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "\0", 1)); + TEST(!strncmp((dest+4), ref_buf, MAX_LEN-4)); + + memset(dest_buf, mask_char, BUF_LEN); + TEST(0 == CU_translate_special_characters("&", dest, 5)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "\0", 1)); + TEST(!strncmp((dest+5), ref_buf, MAX_LEN-5)); + + memset(dest_buf, mask_char, BUF_LEN); + TEST(1 == CU_translate_special_characters("&", dest, 6)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "&\0", 6)); + TEST(!strncmp((dest+6), ref_buf, MAX_LEN-6)); + + /* maxlen=0 */ + memset(dest_buf, mask_char, BUF_LEN); + strcpy(dest, "random initialized string"); + TEST(0 == CU_translate_special_characters("some <", dest, 0)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strcmp(dest, "random initialized string")); + TEST(!strncmp(dest+strlen(dest)+1, ref_buf, MAX_LEN-strlen(dest)-1)); + + /* maxlen < len(converted szSrc) */ + memset(dest_buf, mask_char, BUF_LEN); + TEST(0 == CU_translate_special_characters("some <", dest, 1)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "\0", 1)); + TEST(!strncmp((dest+1), ref_buf, MAX_LEN-1)); + + memset(dest_buf, mask_char, BUF_LEN); + TEST(0 == CU_translate_special_characters("some <", dest, 2)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "\0", 1)); + TEST(!strncmp((dest+2), ref_buf, MAX_LEN-2)); + + memset(dest_buf, mask_char, BUF_LEN); + TEST(0 == CU_translate_special_characters("some <", dest, 5)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "\0", 1)); + TEST(!strncmp((dest+5), ref_buf, MAX_LEN-5)); + + memset(dest_buf, mask_char, BUF_LEN); + TEST(0 == CU_translate_special_characters("some <", dest, 10)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "\0", 1)); + TEST(!strncmp((dest+10), ref_buf, MAX_LEN-10)); + + memset(dest_buf, mask_char, BUF_LEN); + TEST(0 == CU_translate_special_characters("some <", dest, 20)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "\0", 1)); + TEST(!strncmp((dest+20), ref_buf, MAX_LEN-20)); + + memset(dest_buf, mask_char, BUF_LEN); + TEST(0 == CU_translate_special_characters("some <", dest, 24)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "\0", 1)); + TEST(!strncmp((dest+24), ref_buf, MAX_LEN-24)); + + memset(dest_buf, mask_char, BUF_LEN); + TEST(0 == CU_translate_special_characters("some <", dest, 25)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "\0", 1)); + TEST(!strncmp((dest+25), ref_buf, MAX_LEN-25)); + + memset(dest_buf, mask_char, BUF_LEN); + TEST(0 == CU_translate_special_characters("some <", dest, 37)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "\0", 1)); + TEST(!strncmp((dest+37), ref_buf, MAX_LEN-37)); + + /* maxlen > len(converted szSrc) */ + memset(dest_buf, mask_char, BUF_LEN); + TEST(4 == CU_translate_special_characters("some <", dest, 38)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "some <<string & another>\0", 38)); + TEST(!strncmp((dest+38), ref_buf, MAX_LEN-38)); + + /* maxlen > len(converted szSrc) */ + memset(dest_buf, mask_char, BUF_LEN); + TEST(4 == CU_translate_special_characters("some <", dest, MAX_LEN)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "some <<string & another>\0", 38)); + + /* no special characters */ + memset(dest_buf, mask_char, BUF_LEN); + TEST(0 == CU_translate_special_characters("some string or another", dest, MAX_LEN)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strncmp(dest, "some string or another\0", 23)); + + /* only special characters */ + memset(dest_buf, mask_char, BUF_LEN); + TEST(11 == CU_translate_special_characters("<><><<>>&&&", dest, MAX_LEN)); + TEST(!strncmp(dest_buf, ref_buf, MAX_LEN)); + TEST(!strcmp(dest, "<><><<>>&&&")); +} + +static void test_CU_translated_strlen(void) +{ + /* empty src */ + TEST(0 == CU_translated_strlen("")); + + /* 1 char src */ + TEST(1 == CU_translated_strlen("#")); + TEST(5 == CU_translated_strlen("&")); + TEST(4 == CU_translated_strlen("<")); + TEST(4 == CU_translated_strlen(">")); + TEST(1 == CU_translated_strlen("?")); + + /* 2 char src */ + TEST(2 == CU_translated_strlen("#@")); + TEST(10 == CU_translated_strlen("&&")); + TEST(9 == CU_translated_strlen(">&")); + + /* longer src */ + TEST(37 == CU_translated_strlen("some <")); + TEST(22 == CU_translated_strlen("some string or another")); + TEST(47 == CU_translated_strlen("<><><<>>&&&")); +} + +static void test_CU_compare_strings(void) +{ + TEST(0 == CU_compare_strings("","")); + TEST(0 == CU_compare_strings("@","@")); + TEST(0 == CU_compare_strings("D","d")); + TEST(0 == CU_compare_strings("s1","s1")); + TEST(0 == CU_compare_strings("s1","S1")); + TEST(0 != CU_compare_strings("s1","s12")); + TEST(0 == CU_compare_strings("this is string 1","tHIS iS sTRING 1")); + TEST(0 == CU_compare_strings("i have \t a tab!","I have \t a tab!")); + TEST(0 != CU_compare_strings("not the same"," not the same")); +} + +static void test_CU_trim(void) +{ + char string[MAX_LEN]; + + strcpy(string, ""); + CU_trim(string); + TEST(!strcmp("", string)); + + strcpy(string, " "); + CU_trim(string); + TEST(!strcmp("", string)); + + strcpy(string, " "); + CU_trim(string); + TEST(!strcmp("", string)); + + strcpy(string, " b"); + CU_trim(string); + TEST(!strcmp("b", string)); + + strcpy(string, " B"); + CU_trim(string); + TEST(!strcmp("B", string)); + + strcpy(string, "s "); + CU_trim(string); + TEST(!strcmp("s", string)); + + strcpy(string, "S "); + CU_trim(string); + TEST(!strcmp("S", string)); + + strcpy(string, " 5 "); + CU_trim(string); + TEST(!strcmp("5", string)); + + strcpy(string, "~ & ^ ( ^ "); + CU_trim(string); + TEST(!strcmp("~ & ^ ( ^", string)); + + strcpy(string, " ~ & ^ ( ^"); + CU_trim(string); + TEST(!strcmp("~ & ^ ( ^", string)); + + strcpy(string, " ~ & ^ ( ^ "); + CU_trim(string); + TEST(!strcmp("~ & ^ ( ^", string)); +} + +static void test_CU_trim_left(void) +{ + char string[MAX_LEN]; + + strcpy(string, ""); + CU_trim_left(string); + TEST(!strcmp("", string)); + + strcpy(string, " "); + CU_trim_left(string); + TEST(!strcmp("", string)); + + strcpy(string, " "); + CU_trim_left(string); + TEST(!strcmp("", string)); + + strcpy(string, " b"); + CU_trim_left(string); + TEST(!strcmp("b", string)); + + strcpy(string, " B"); + CU_trim_left(string); + TEST(!strcmp("B", string)); + + strcpy(string, "s "); + CU_trim_left(string); + TEST(!strcmp("s ", string)); + + strcpy(string, "S "); + CU_trim_left(string); + TEST(!strcmp("S ", string)); + + strcpy(string, " 5 "); + CU_trim_left(string); + TEST(!strcmp("5 ", string)); + + strcpy(string, "~ & ^ ( ^ "); + CU_trim_left(string); + TEST(!strcmp("~ & ^ ( ^ ", string)); + + strcpy(string, " ~ & ^ ( ^"); + CU_trim_left(string); + TEST(!strcmp("~ & ^ ( ^", string)); + + strcpy(string, " ~ & ^ ( ^ "); + CU_trim_left(string); + TEST(!strcmp("~ & ^ ( ^ ", string)); +} + +static void test_CU_trim_right(void) +{ + char string[MAX_LEN]; + + strcpy(string, ""); + CU_trim_right(string); + TEST(!strcmp("", string)); + + strcpy(string, " "); + CU_trim_right(string); + TEST(!strcmp("", string)); + + strcpy(string, " "); + CU_trim_right(string); + TEST(!strcmp("", string)); + + strcpy(string, " b"); + CU_trim_right(string); + TEST(!strcmp(" b", string)); + + strcpy(string, " B"); + CU_trim_right(string); + TEST(!strcmp(" B", string)); + + strcpy(string, "s "); + CU_trim_right(string); + TEST(!strcmp("s", string)); + + strcpy(string, "S "); + CU_trim_right(string); + TEST(!strcmp("S", string)); + + strcpy(string, " 5 "); + CU_trim_right(string); + TEST(!strcmp(" 5", string)); + + strcpy(string, "~ & ^ ( ^ "); + CU_trim_right(string); + TEST(!strcmp("~ & ^ ( ^", string)); + + strcpy(string, " ~ & ^ ( ^"); + CU_trim_right(string); + TEST(!strcmp(" ~ & ^ ( ^", string)); + + strcpy(string, " ~ & ^ ( ^ "); + CU_trim_right(string); + TEST(!strcmp(" ~ & ^ ( ^", string)); +} + +static void test_CU_number_width(void) +{ + TEST(1 == CU_number_width(0)); + TEST(1 == CU_number_width(1)); + TEST(2 == CU_number_width(-1)); + TEST(4 == CU_number_width(2346)); + TEST(7 == CU_number_width(-257265)); + TEST(9 == CU_number_width(245723572)); + TEST(9 == CU_number_width(-45622572)); +} + +void test_cunit_Util(void) +{ + + test_cunit_start_tests("Util.c"); + + test_CU_translate_special_characters(); + test_CU_translated_strlen(); + test_CU_compare_strings(); + test_CU_trim(); + test_CU_trim_left(); + test_CU_trim_right(); + test_CU_number_width(); + + test_cunit_end_tests(); +} + +#endif /* CUNIT_BUILD_TESTS */ diff --git a/pde-test-host/pde-test-host/debian/changelog b/pde-test-host/pde-test-host/debian/changelog new file mode 100644 index 0000000..e26ae35 --- /dev/null +++ b/pde-test-host/pde-test-host/debian/changelog @@ -0,0 +1,5 @@ +pde-test-host (1.0.0-1) unstable; urgency=medium + + * Initial release + + -- William Schwartz Fri, 13 Apr 2018 09:12:35 -0400 diff --git a/pde-test-host/pde-test-host/debian/compat b/pde-test-host/pde-test-host/debian/compat new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/pde-test-host/pde-test-host/debian/compat @@ -0,0 +1 @@ +9 diff --git a/pde-test-host/pde-test-host/debian/control b/pde-test-host/pde-test-host/debian/control new file mode 100644 index 0000000..27faa29 --- /dev/null +++ b/pde-test-host/pde-test-host/debian/control @@ -0,0 +1,13 @@ +Source: pde-test-host +Section: devel +Priority: optional +Maintainer: Bill Schwartz +Build-Depends: debhelper (>= 9) +Standards-Version: 4.1.3 + +Package: pde-test-host +Architecture: any +Section:utils +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: SONiC PDE test utility for SAI + This utility intended to be used as part of the PDE. diff --git a/pde-test-host/pde-test-host/debian/copyright b/pde-test-host/pde-test-host/debian/copyright new file mode 100644 index 0000000..1226fd0 --- /dev/null +++ b/pde-test-host/pde-test-host/debian/copyright @@ -0,0 +1 @@ +We have a copyright diff --git a/pde-test-host/pde-test-host/debian/files b/pde-test-host/pde-test-host/debian/files new file mode 100644 index 0000000..eda4b3f --- /dev/null +++ b/pde-test-host/pde-test-host/debian/files @@ -0,0 +1,2 @@ +pdk-test-host_1.0.0-1_amd64.buildinfo devel optional +pdk-test-host_1.0.0-1_amd64.deb utils optional diff --git a/pde-test-host/pde-test-host/debian/install b/pde-test-host/pde-test-host/debian/install new file mode 100644 index 0000000..eeb26d9 --- /dev/null +++ b/pde-test-host/pde-test-host/debian/install @@ -0,0 +1,2 @@ +pde-test-host /usr/bin/ +parse_port_config.py /usr/bin diff --git a/pde-test-host/pde-test-host/debian/rules b/pde-test-host/pde-test-host/debian/rules new file mode 100755 index 0000000..3973dad --- /dev/null +++ b/pde-test-host/pde-test-host/debian/rules @@ -0,0 +1,9 @@ +#!/usr/bin/make -f + +DH_VERBOSE=1 +%: + dh $@ + +override_dh_auto_clean: + dh_auto_clean + diff --git a/pde-test-host/pde-test-host/include/Automated.h b/pde-test-host/pde-test-host/include/Automated.h new file mode 100755 index 0000000..2acc694 --- /dev/null +++ b/pde-test-host/pde-test-host/include/Automated.h @@ -0,0 +1,90 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2001 Anil Kumar + * Copyright (C) 2004-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 + */ + +/* + * Automated Interface (generates HTML Report Files). + * + * Feb 2002 Initial implementation (AK) + * + * 13-Feb-2002 Single interface to automated_run_tests. (AK) + * + * 20-Jul-2004 New interface, doxygen comments. (JDS) + */ + +/** @file + * Automated testing interface with xml output (user interface). + */ +/** @addtogroup Automated + * @{ + */ + +#ifndef CUNIT_AUTOMATED_H_SEEN +#define CUNIT_AUTOMATED_H_SEEN + +#include "CUnit.h" +#include "TestDB.h" + +#ifdef __cplusplus +extern "C" { +#endif + +CU_EXPORT void CU_automated_run_tests(void); +/**< + * Runs 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). + */ + +CU_EXPORT CU_ErrorCode CU_list_tests_to_file(void); +/**< + * Generates 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_EXPORT void CU_set_output_filename(const char* szFilenameRoot); +/**< + * Sets 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. + */ + +#ifdef USE_DEPRECATED_CUNIT_NAMES +/** Deprecated (version 1). @deprecated Use CU_automated_run_tests(). */ +#define automated_run_tests() CU_automated_run_tests() +/** Deprecated (version 1). @deprecated Use CU_set_output_filename(). */ +#define set_output_filename(x) CU_set_output_filename((x)) +#endif /* USE_DEPRECATED_CUNIT_NAMES */ + +#ifdef __cplusplus +} +#endif +#endif /* CUNIT_AUTOMATED_H_SEEN */ +/** @} */ diff --git a/pde-test-host/pde-test-host/include/Basic.h b/pde-test-host/pde-test-host/include/Basic.h new file mode 100755 index 0000000..d8a638d --- /dev/null +++ b/pde-test-host/pde-test-host/include/Basic.h @@ -0,0 +1,113 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2004-2006 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 + */ + +/* + * Interface for simple test runner. + * + * 11-Aug-2004 Initial implementation of basic test runner interface. (JDS) + */ + +/** @file + * Basic interface with output to stdout. + */ +/** @addtogroup Basic + * @{ + */ + +#ifndef CUNIT_BASIC_H_SEEN +#define CUNIT_BASIC_H_SEEN + +#include "CUnit.h" +#include "TestDB.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Run modes for the basic interface. */ +typedef enum { + CU_BRM_NORMAL = 0, /**< Normal mode - failures and run summary are printed [default]. */ + CU_BRM_SILENT, /**< Silent mode - no output is printed except framework error messages. */ + CU_BRM_VERBOSE /**< Verbose mode - maximum output of run details. */ +} CU_BasicRunMode; + +CU_EXPORT CU_ErrorCode CU_basic_run_tests(void); +/**< + * Runs all registered CUnit tests using the basic interface. + * The default CU_BasicRunMode is used unless it has been + * previously changed using CU_basic_set_mode(). The CUnit test + * registry must have been initialized before calling this function. + * + * @return A CU_ErrorCode indicating the framework error condition, including + * CUE_NOREGISTRY - Registry has not been initialized. + */ + +CU_EXPORT CU_ErrorCode CU_basic_run_suite(CU_pSuite pSuite); +/**< + * Runs all tests for a specific suite in the basic interface. + * If pSuite is NULL, the function returns without taking any + * action. The default CU_BasicRunMode is used unless it has + * been changed using CU_basic_set_mode(). + * + * @param pSuite The CU_Suite to run. + * @return A CU_ErrorCode indicating the framework error condition, including + * CUE_NOSUITE - pSuite was NULL. + */ + +CU_EXPORT CU_ErrorCode CU_basic_run_test(CU_pSuite pSuite, CU_pTest pTest); +/**< + * Runs a single test in a specific suite in the basic interface. + * If pSuite or pTest is NULL, the function returns without + * taking any action. The default CU_BasicRunMode is used unless + * it has been changed using CU_basic_set_mode. + * + * @param pSuite The CU_Suite holding the CU_Test to run. + * @param pTest The CU_Test to run. + * @return A CU_ErrorCode indicating the framework error condition, including + * CUE_NOSUITE - pSuite was NULL. + * CUE_NOTEST - pTest was NULL. + */ + +CU_EXPORT void CU_basic_set_mode(CU_BasicRunMode mode); +/**< Sets the run mode for the basic interface. + * @param mode The new CU_BasicRunMode for subsequent test + * runs using the basic interface. + */ + +CU_EXPORT CU_BasicRunMode CU_basic_get_mode(void); +/**< Retrieves the current run mode for the basic interface. + * @return The current CU_BasicRunMode setting for test + * runs using the basic interface. + */ + +CU_EXPORT void CU_basic_show_failures(CU_pFailureRecord pFailure); +/**< + * Prints a summary of run failures to stdout. + * This is provided for user convenience upon request, and does + * not take into account the current run mode. The failures are + * printed to stdout independent of the most recent run mode. + * + * @param pFailure List of CU_pFailureRecord's to output. + */ + +#ifdef __cplusplus +} +#endif +#endif /* CUNIT_BASIC_H_SEEN */ +/** @} */ diff --git a/pde-test-host/pde-test-host/include/CUError.h b/pde-test-host/pde-test-host/include/CUError.h new file mode 100755 index 0000000..c9943c1 --- /dev/null +++ b/pde-test-host/pde-test-host/include/CUError.h @@ -0,0 +1,199 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2001 Anil Kumar + * Copyright (C) 2004-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 + */ + +/* + * Contains CUnit error codes which can be used externally. + * + * Aug 2001 Initial implementation. (AK) + * + * 02/Oct/2001 Added proper Eror Codes. (AK) + * + * 13-Oct-2001 Added Error Codes for Duplicate TestGroup and Test. (AK) + * + * 03-Aug-2004 Converted error code macros to an enum, doxygen comments, moved + * error handing code here, changed file name from Errno.h, added + * error codes for file open errors, added error action selection. (JDS) + * + * 05-Sep-2004 Added internal test interface. (JDS) + */ + +/** @file + * Error handling functions (user interface). + * CUnit uses a simple (and conventional) error handling strategy. + * Functions that can generate errors set (and usually return) an + * error code to indicate the run status. The error code can be + * inspected using the CU_get_error() function. A descriptive + * error message can be retrieved using CU_get_error_msg(). + */ +/** @addtogroup Framework + * @{ + */ + +#ifndef CUNIT_CUERROR_H_SEEN +#define CUNIT_CUERROR_H_SEEN + +#include + +/*------------------------------------------------------------------------*/ +/** CUnit error codes. + * If codes are added or removed, be sure to make a change to the + * error messages in CUError.c/get_error_desc(). + * @see CU_set_error() + * @see CU_get_error() + * @see CU_get_error_msg() + */ +typedef enum { + /* basic errors */ + CUE_SUCCESS = 0, /**< No error condition. */ + CUE_NOMEMORY = 1, /**< Memory allocation failed. */ + + /* Test Registry Level Errors */ + CUE_NOREGISTRY = 10, /**< Test registry not initialized. */ + CUE_REGISTRY_EXISTS = 11, /**< Attempt to CU_set_registry() without CU_cleanup_registry(). */ + + /* Test Suite Level Errors */ + CUE_NOSUITE = 20, /**< A required CU_pSuite pointer was NULL. */ + CUE_NO_SUITENAME = 21, /**< Required CU_Suite name not provided. */ + CUE_SINIT_FAILED = 22, /**< Suite initialization failed. */ + CUE_SCLEAN_FAILED = 23, /**< Suite cleanup failed. */ + CUE_DUP_SUITE = 24, /**< Duplicate suite name not allowed. */ + CUE_SUITE_INACTIVE = 25, /**< Test run initiated for an inactive suite. */ + + /* Test Case Level Errors */ + CUE_NOTEST = 30, /**< A required CU_pTest or CU_TestFunc pointer was NULL. */ + CUE_NO_TESTNAME = 31, /**< Required CU_Test name not provided. */ + CUE_DUP_TEST = 32, /**< Duplicate test case name not allowed. */ + CUE_TEST_NOT_IN_SUITE = 33, /**< Test not registered in specified suite. */ + CUE_TEST_INACTIVE = 34, /**< Test run initiated for an inactive test. */ + + /* File handling errors */ + CUE_FOPEN_FAILED = 40, /**< An error occurred opening a file. */ + CUE_FCLOSE_FAILED = 41, /**< An error occurred closing a file. */ + CUE_BAD_FILENAME = 42, /**< A bad filename was requested (NULL, empty, nonexistent, etc.). */ + CUE_WRITE_ERROR = 43 /**< An error occurred during a write to a file. */ +} CU_ErrorCode; + +/*------------------------------------------------------------------------*/ +/** CUnit error action codes. + * These are used to set the action desired when an error + * condition is detected in the CUnit framework. + * @see CU_set_error_action() + * @see CU_get_error_action() + */ +typedef enum CU_ErrorAction { + CUEA_IGNORE, /**< Runs should be continued when an error condition occurs (if possible). */ + CUEA_FAIL, /**< Runs should be stopped when an error condition occurs. */ + CUEA_ABORT /**< The application should exit() when an error conditions occurs. */ +} CU_ErrorAction; + +/* Error handling & reporting functions. */ + +#include "CUnit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +CU_EXPORT CU_ErrorCode CU_get_error(void); +/**< + * Retrieves the current CUnit framework error code. + * CUnit implementation functions set the error code to indicate the + * status of the most recent operation. In general, the CUnit functions + * will clear the code to CUE_SUCCESS, then reset it to a specific error + * code if an exception condition is encountered. Some functions + * return the code, others leave it to the user to inspect if desired. + * + * @return The current error condition code. + * @see CU_get_error_msg() + * @see CU_ErrorCode + */ + +CU_EXPORT const char* CU_get_error_msg(void); +/**< + * Retrieves a message corresponding to the current framework error code. + * CUnit implementation functions set the error code to indicate the + * of the most recent operation. In general, the CUnit functions will + * clear the code to CUE_SUCCESS, then reset it to a specific error + * code if an exception condition is encountered. This function allows + * the user to retrieve a descriptive error message corresponding to the + * error code set by the last operation. + * + * @return A message corresponding to the current error condition. + * @see CU_get_error() + * @see CU_ErrorCode + */ + +CU_EXPORT void CU_set_error_action(CU_ErrorAction action); +/**< + * Sets the action to take when a framework error condition occurs. + * This function should be used to specify the action to take + * when an error condition is encountered. The default action is + * CUEA_IGNORE, which results in errors being ignored and test runs + * being continued (if possible). A value of CUEA_FAIL causes test + * runs to stop as soon as an error condition occurs, while + * CU_ABORT causes the application to exit on any error. + * + * @param action CU_ErrorAction indicating the new error action. + * @see CU_get_error_action() + * @see CU_set_error() + * @see CU_ErrorAction + */ + +CU_EXPORT CU_ErrorAction CU_get_error_action(void); +/**< + * Retrieves the current framework error action code. + * + * @return The current error action code. + * @see CU_set_error_action() + * @see CU_set_error() + * @see CU_ErrorAction + */ + +#ifdef CUNIT_BUILD_TESTS +void test_cunit_CUError(void); +#endif + +/* Internal function - users should not generally call this function */ +CU_EXPORT void CU_set_error(CU_ErrorCode error); +/**< + * Sets the CUnit framework error code. + * This function is used internally by CUnit implementation functions + * when an error condition occurs within the framework. It should + * not generally be called by user code. NOTE that if the current + * error action is CUEA_ABORT, then calling this function will + * result in exit() being called for the current application. + * + * @param error CU_ErrorCode indicating the current error condition. + * @see CU_get_error() + * @see CU_get_error_msg() + * @see CU_ErrorCode + */ + +#ifdef __cplusplus +} +#endif + +#ifdef USE_DEPRECATED_CUNIT_NAMES +/** Deprecated (version 1). @deprecated Use CU_get_error_msg(). */ +#define get_error() CU_get_error_msg() +#endif /* USE_DEPRECATED_CUNIT_NAMES */ + +#endif /* CUNIT_CUERROR_H_SEEN */ +/** @} */ diff --git a/pde-test-host/pde-test-host/include/CUnit.h b/pde-test-host/pde-test-host/include/CUnit.h new file mode 100755 index 0000000..9592eda --- /dev/null +++ b/pde-test-host/pde-test-host/include/CUnit.h @@ -0,0 +1,383 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2001 Anil Kumar + * Copyright (C) 2004-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 + */ + +/* + * ASSERT Macro definitions and general CUnit configuration definitions. + * + * 09/Aug/2001 ASSERT definitions. (AK) + * + * 12/Mar/2003 New Assert definitions. (AK) + * + * 27/Jul/2003 Modified ASSERT_XXX Macro definitions. (AK) + * + * 15-Jul-2004 New interface, changed action on assert failure to not + * return, provided _FATAL versions of assertions to return + * from test function on failure. (JDS) + * + * 01-Sep-2004 Modified assertions for setjmp/longjmp mechanism of + * aborting test runs, added CU_FAIL and CU_PASS macros. (JDS) + * + * 07-May-2005 Added CU_ prefix to remaining CUnit defines (BOOL, TRUE, + * FALSE, MAX_...). Added CU_UNREFERENCED_PARAMETER() define. (JDS) + */ + +/** @file + * Basic CUnit include file for user and system code. + * Defines macros for assertions for use in user test cases. + * Basic system macro definitions also appear here. + */ +/** @addtogroup Framework + * @{ + */ + +#ifndef CUNIT_CUNIT_H_SEEN +#define CUNIT_CUNIT_H_SEEN + +#include +#include + +/** CUnit version number. */ +#define CU_VERSION "2.1-2" + +/* Max string lengths for names (includes terminating NULL. */ +/** Maximum length of a test name string. */ +#define CU_MAX_TEST_NAME_LENGTH 256 +/** Maximim length of a suite name string. */ +#define CU_MAX_SUITE_NAME_LENGTH 256 + +/* Global type Definitions to be used for boolean operators. */ +#ifndef CU_BOOL + /** Boolean type for CUnit use. */ + #define CU_BOOL int +#endif + +#ifndef CU_TRUE + /** Boolean TRUE for CUnit use. */ + #define CU_TRUE 1 +#endif + +#ifndef CU_FALSE + /** Boolean FALSE for CUnit use. */ + #define CU_FALSE 0 +#endif + +#ifndef CU_UNREFERENCED_PARAMETER + /** Consistent approach to referencing unused parameters. */ + #define CU_UNREFERENCED_PARAMETER(x) (void)x +#endif + +#ifndef CU_MAX +# define CU_MAX(a,b) (((a) >= (b)) ? (a) : (b)) +#endif + +#ifndef CU_MIN +# define CU_MIN(a,b) (((a) >= (b)) ? (b) : (a)) +#endif + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) +# ifdef CU_DLL +# ifdef CU_BUILD_DLL +# define CU_EXPORT __declspec(dllexport) +# else +# define CU_EXPORT __declspec(dllimport) +# endif +# else +# define CU_EXPORT +# endif +# ifdef _MSC_VER +# define snprintf _snprintf +# endif +#else +# define CU_EXPORT +#endif /* WIN32 */ + +#include "CUError.h" +#include "TestDB.h" /* not needed here - included for user convenience */ +#include "TestRun.h" /* not needed here - include (after BOOL define) for user convenience */ + +/** Record a pass condition without performing a logical test. */ +#define CU_PASS(msg) \ + { CU_assertImplementation(CU_TRUE, __LINE__, ("CU_PASS(" #msg ")"), __FILE__, "", CU_FALSE); } + +/** Simple assertion. + * Reports failure with no other action. + */ +#define CU_ASSERT(value) \ + { CU_assertImplementation((value), __LINE__, #value, __FILE__, "", CU_FALSE); } + +/** Simple assertion. + * Reports failure and causes test to abort. + */ +#define CU_ASSERT_FATAL(value) \ + { CU_assertImplementation((value), __LINE__, #value, __FILE__, "", CU_TRUE); } + +/** Simple assertion. + * Reports failure with no other action. + */ +#define CU_TEST(value) \ + { CU_assertImplementation((value), __LINE__, #value, __FILE__, "", CU_FALSE); } + +/** Simple assertion. + * Reports failure and causes test to abort. + */ +#define CU_TEST_FATAL(value) \ + { CU_assertImplementation((value), __LINE__, #value, __FILE__, "", CU_TRUE); } + +/** Record a failure without performing a logical test. */ +#define CU_FAIL(msg) \ + { CU_assertImplementation(CU_FALSE, __LINE__, ("CU_FAIL(" #msg ")"), __FILE__, "", CU_FALSE); } + +/** Record a failure without performing a logical test, and abort test. */ +#define CU_FAIL_FATAL(msg) \ + { CU_assertImplementation(CU_FALSE, __LINE__, ("CU_FAIL_FATAL(" #msg ")"), __FILE__, "", CU_TRUE); } + +/** Asserts that value is CU_TRUE. + * Reports failure with no other action. + */ +#define CU_ASSERT_TRUE(value) \ + { CU_assertImplementation((value), __LINE__, ("CU_ASSERT_TRUE(" #value ")"), __FILE__, "", CU_FALSE); } + +/** Asserts that value is CU_TRUE. + * Reports failure and causes test to abort. + */ +#define CU_ASSERT_TRUE_FATAL(value) \ + { CU_assertImplementation((value), __LINE__, ("CU_ASSERT_TRUE_FATAL(" #value ")"), __FILE__, "", CU_TRUE); } + +/** Asserts that value is CU_FALSE. + * Reports failure with no other action. + */ +#define CU_ASSERT_FALSE(value) \ + { CU_assertImplementation(!(value), __LINE__, ("CU_ASSERT_FALSE(" #value ")"), __FILE__, "", CU_FALSE); } + +/** Asserts that value is CU_FALSE. + * Reports failure and causes test to abort. + */ +#define CU_ASSERT_FALSE_FATAL(value) \ + { CU_assertImplementation(!(value), __LINE__, ("CU_ASSERT_FALSE_FATAL(" #value ")"), __FILE__, "", CU_TRUE); } + +/** Asserts that actual == expected. + * Reports failure with no other action. + */ +#define CU_ASSERT_EQUAL(actual, expected) \ + { CU_assertImplementation(((actual) == (expected)), __LINE__, ("CU_ASSERT_EQUAL(" #actual "," #expected ")"), __FILE__, "", CU_FALSE); } + +/** Asserts that actual == expected. + * Reports failure and causes test to abort. + */ +#define CU_ASSERT_EQUAL_FATAL(actual, expected) \ + { CU_assertImplementation(((actual) == (expected)), __LINE__, ("CU_ASSERT_EQUAL_FATAL(" #actual "," #expected ")"), __FILE__, "", CU_TRUE); } + +/** Asserts that actual != expected. + * Reports failure with no other action. + */ +#define CU_ASSERT_NOT_EQUAL(actual, expected) \ + { CU_assertImplementation(((actual) != (expected)), __LINE__, ("CU_ASSERT_NOT_EQUAL(" #actual "," #expected ")"), __FILE__, "", CU_FALSE); } + +/** Asserts that actual != expected. + * Reports failure and causes test to abort. + */ +#define CU_ASSERT_NOT_EQUAL_FATAL(actual, expected) \ + { CU_assertImplementation(((actual) != (expected)), __LINE__, ("CU_ASSERT_NOT_EQUAL_FATAL(" #actual "," #expected ")"), __FILE__, "", CU_TRUE); } + +/** Asserts that pointers actual == expected. + * Reports failure with no other action. + */ +#define CU_ASSERT_PTR_EQUAL(actual, expected) \ + { CU_assertImplementation(((void*)(actual) == (void*)(expected)), __LINE__, ("CU_ASSERT_PTR_EQUAL(" #actual "," #expected ")"), __FILE__, "", CU_FALSE); } + +/** Asserts that pointers actual == expected. + * Reports failure and causes test to abort. + */ +#define CU_ASSERT_PTR_EQUAL_FATAL(actual, expected) \ + { CU_assertImplementation(((void*)(actual) == (void*)(expected)), __LINE__, ("CU_ASSERT_PTR_EQUAL_FATAL(" #actual "," #expected ")"), __FILE__, "", CU_TRUE); } + +/** Asserts that pointers actual != expected. + * Reports failure with no other action. + */ +#define CU_ASSERT_PTR_NOT_EQUAL(actual, expected) \ + { CU_assertImplementation(((void*)(actual) != (void*)(expected)), __LINE__, ("CU_ASSERT_PTR_NOT_EQUAL(" #actual "," #expected ")"), __FILE__, "", CU_FALSE); } + +/** Asserts that pointers actual != expected. + * Reports failure and causes test to abort. + */ +#define CU_ASSERT_PTR_NOT_EQUAL_FATAL(actual, expected) \ + { CU_assertImplementation(((void*)(actual) != (void*)(expected)), __LINE__, ("CU_ASSERT_PTR_NOT_EQUAL_FATAL(" #actual "," #expected ")"), __FILE__, "", CU_TRUE); } + +/** Asserts that pointer value is NULL. + * Reports failure with no other action. + */ +#define CU_ASSERT_PTR_NULL(value) \ + { CU_assertImplementation((NULL == (void*)(value)), __LINE__, ("CU_ASSERT_PTR_NULL(" #value")"), __FILE__, "", CU_FALSE); } + +/** Asserts that pointer value is NULL. + * Reports failure and causes test to abort. + */ +#define CU_ASSERT_PTR_NULL_FATAL(value) \ + { CU_assertImplementation((NULL == (void*)(value)), __LINE__, ("CU_ASSERT_PTR_NULL_FATAL(" #value")"), __FILE__, "", CU_TRUE); } + +/** Asserts that pointer value is not NULL. + * Reports failure with no other action. + */ +#define CU_ASSERT_PTR_NOT_NULL(value) \ + { CU_assertImplementation((NULL != (void*)(value)), __LINE__, ("CU_ASSERT_PTR_NOT_NULL(" #value")"), __FILE__, "", CU_FALSE); } + +/** Asserts that pointer value is not NULL. + * Reports failure and causes test to abort. + */ +#define CU_ASSERT_PTR_NOT_NULL_FATAL(value) \ + { CU_assertImplementation((NULL != (void*)(value)), __LINE__, ("CU_ASSERT_PTR_NOT_NULL_FATAL(" #value")"), __FILE__, "", CU_TRUE); } + +/** Asserts that string actual == expected. + * Reports failure with no other action. + */ +#define CU_ASSERT_STRING_EQUAL(actual, expected) \ + { CU_assertImplementation(!(strcmp((const char*)(actual), (const char*)(expected))), __LINE__, ("CU_ASSERT_STRING_EQUAL(" #actual "," #expected ")"), __FILE__, "", CU_FALSE); } + +/** Asserts that string actual == expected. + * Reports failure and causes test to abort. + */ +#define CU_ASSERT_STRING_EQUAL_FATAL(actual, expected) \ + { CU_assertImplementation(!(strcmp((const char*)(actual), (const char*)(expected))), __LINE__, ("CU_ASSERT_STRING_EQUAL_FATAL(" #actual "," #expected ")"), __FILE__, "", CU_TRUE); } + +/** Asserts that string actual != expected. + * Reports failure with no other action. + */ +#define CU_ASSERT_STRING_NOT_EQUAL(actual, expected) \ + { CU_assertImplementation((strcmp((const char*)(actual), (const char*)(expected))), __LINE__, ("CU_ASSERT_STRING_NOT_EQUAL(" #actual "," #expected ")"), __FILE__, "", CU_FALSE); } + +/** Asserts that string actual != expected. + * Reports failure and causes test to abort. + */ +#define CU_ASSERT_STRING_NOT_EQUAL_FATAL(actual, expected) \ + { CU_assertImplementation((strcmp((const char*)(actual), (const char*)(expected))), __LINE__, ("CU_ASSERT_STRING_NOT_EQUAL_FATAL(" #actual "," #expected ")"), __FILE__, "", CU_TRUE); } + +/** Asserts that string actual == expected with length specified. + * The comparison is limited to count characters. + * Reports failure with no other action. + */ +#define CU_ASSERT_NSTRING_EQUAL(actual, expected, count) \ + { CU_assertImplementation(!(strncmp((const char*)(actual), (const char*)(expected), (size_t)(count))), __LINE__, ("CU_ASSERT_NSTRING_EQUAL(" #actual "," #expected "," #count ")"), __FILE__, "", CU_FALSE); } + +/** Asserts that string actual == expected with length specified. + * The comparison is limited to count characters. + * Reports failure and causes test to abort. + */ +#define CU_ASSERT_NSTRING_EQUAL_FATAL(actual, expected, count) \ + { CU_assertImplementation(!(strncmp((const char*)(actual), (const char*)(expected), (size_t)(count))), __LINE__, ("CU_ASSERT_NSTRING_EQUAL_FATAL(" #actual "," #expected "," #count ")"), __FILE__, "", CU_TRUE); } + +/** Asserts that string actual != expected with length specified. + * The comparison is limited to count characters. + * Reports failure with no other action. + */ +#define CU_ASSERT_NSTRING_NOT_EQUAL(actual, expected, count) \ + { CU_assertImplementation((strncmp((const char*)(actual), (const char*)(expected), (size_t)(count))), __LINE__, ("CU_ASSERT_NSTRING_NOT_EQUAL(" #actual "," #expected "," #count ")"), __FILE__, "", CU_FALSE); } + +/** Asserts that string actual != expected with length specified. + * The comparison is limited to count characters. + * Reports failure and causes test to abort. + */ +#define CU_ASSERT_NSTRING_NOT_EQUAL_FATAL(actual, expected, count) \ + { CU_assertImplementation((strncmp((const char*)(actual), (const char*)(expected), (size_t)(count))), __LINE__, ("CU_ASSERT_NSTRING_NOT_EQUAL_FATAL(" #actual "," #expected "," #count ")"), __FILE__, "", CU_TRUE); } + +/** Asserts that double actual == expected within the specified tolerance. + * If actual is within granularity of expected, the assertion passes. + * Reports failure with no other action. + */ +#define CU_ASSERT_DOUBLE_EQUAL(actual, expected, granularity) \ + { CU_assertImplementation(((fabs((double)(actual) - (expected)) <= fabs((double)(granularity)))), __LINE__, ("CU_ASSERT_DOUBLE_EQUAL(" #actual "," #expected "," #granularity ")"), __FILE__, "", CU_FALSE); } + +/** Asserts that double actual == expected within the specified tolerance. + * If actual is within granularity of expected, the assertion passes. + * Reports failure and causes test to abort. + */ +#define CU_ASSERT_DOUBLE_EQUAL_FATAL(actual, expected, granularity) \ + { CU_assertImplementation(((fabs((double)(actual) - (expected)) <= fabs((double)(granularity)))), __LINE__, ("CU_ASSERT_DOUBLE_EQUAL_FATAL(" #actual "," #expected "," #granularity ")"), __FILE__, "", CU_TRUE); } + +/** Asserts that double actual != expected within the specified tolerance. + * If actual is within granularity of expected, the assertion fails. + * Reports failure with no other action. + */ +#define CU_ASSERT_DOUBLE_NOT_EQUAL(actual, expected, granularity) \ + { CU_assertImplementation(((fabs((double)(actual) - (expected)) > fabs((double)(granularity)))), __LINE__, ("CU_ASSERT_DOUBLE_NOT_EQUAL(" #actual "," #expected "," #granularity ")"), __FILE__, "", CU_FALSE); } + +/** Asserts that double actual != expected within the specified tolerance. + * If actual is within granularity of expected, the assertion fails. + * Reports failure and causes test to abort. + */ +#define CU_ASSERT_DOUBLE_NOT_EQUAL_FATAL(actual, expected, granularity) \ + { CU_assertImplementation(((fabs((double)(actual) - (expected)) > fabs((double)(granularity)))), __LINE__, ("CU_ASSERT_DOUBLE_NOT_EQUAL_FATAL(" #actual "," #expected "," #granularity ")"), __FILE__, "", CU_TRUE); } + +#ifdef USE_DEPRECATED_CUNIT_NAMES + +#ifndef BOOL + /** Deprecated (version 2.0-2). @deprecated Use CU_BOOL. */ + #define BOOL int +#endif + +#ifndef TRUE + /** Deprecated (version 2.0-2). @deprecated Use CU_TRUE. */ + #define TRUE 1 +#endif + +#ifndef FALSE + /** Deprecated (version 2.0-2). @deprecated Use CU_FALSE. */ + #define FALSE 0 +#endif + +/** Deprecated (version 2.0-2). @deprecated Use CU_MAX_TEST_NAME_LENGTH. */ +#define MAX_TEST_NAME_LENGTH 256 +/** Deprecated (version 2.0-2). @deprecated Use CU_MAX_SUITE_NAME_LENGTH. */ +#define MAX_SUITE_NAME_LENGTH 256 + +/** Deprecated (version 1). @deprecated Use CU_ASSERT_FATAL. */ +#define ASSERT(value) { if (FALSE == (int)(value)) { CU_assertImplementation((BOOL)value, __LINE__, #value, __FILE__, "", FALSE); return; }} +/** Deprecated (version 1). @deprecated Use CU_ASSERT_TRUE_FATAL. */ +#define ASSERT_TRUE(value) { if (FALSE == (value)) { CU_assertImplementation(FALSE, __LINE__, ("ASSERT_TRUE(" #value ")"), __FILE__, "", FALSE); return; }} +/** Deprecated (version 1). @deprecated Use CU_ASSERT_FALSE_FATAL. */ +#define ASSERT_FALSE(value) { if (FALSE != (value)) { CU_assertImplementation(FALSE, __LINE__, ("ASSERT_FALSE(" #value ")"), __FILE__, "", FALSE); return; }} +/** Deprecated (version 1). @deprecated Use CU_ASSERT_EQUAL_FATAL. */ +#define ASSERT_EQUAL(actual, expected) { if ((actual) != (expected)) { CU_assertImplementation(FALSE, __LINE__, ("ASSERT_EQUAL(" #actual "," #expected ")"), __FILE__, "", FALSE); return; }} +/** Deprecated (version 1). @deprecated Use CU_ASSERT_NOT_EQUAL_FATAL. */ +#define ASSERT_NOT_EQUAL(actual, expected) { if ((void*)(actual) == (void*)(expected)) { CU_assertImplementation(FALSE, __LINE__, ("ASSERT_NOT_EQUAL(" #actual "," #expected ")"), __FILE__, "", FALSE); return; }} +/** Deprecated (version 1). @deprecated Use CU_ASSERT_PTR_EQUAL_FATAL. */ +#define ASSERT_PTR_EQUAL(actual, expected) { if ((void*)(actual) != (void*)(expected)) { CU_assertImplementation(FALSE, __LINE__, ("ASSERT_PTR_EQUAL(" #actual "," #expected ")"), __FILE__, "", FALSE); return; }} +/** Deprecated (version 1). @deprecated Use CU_ASSERT_PTR_NOT_EQUAL_FATAL. */ +#define ASSERT_PTR_NOT_EQUAL(actual, expected) { if ((void*)(actual) == (void*)(expected)) { CU_assertImplementation(FALSE, __LINE__, ("ASSERT_PTR_NOT_EQUAL(" #actual "," #expected ")"), __FILE__, "", FALSE); return; }} +/** Deprecated (version 1). @deprecated Use CU_ASSERT_PTR_NULL_FATAL. */ +#define ASSERT_PTR_NULL(value) { if (NULL != (void*)(value)) { CU_assertImplementation(FALSE, __LINE__, ("ASSERT_PTR_NULL(" #value")"), __FILE__, "", FALSE); return; }} +/** Deprecated (version 1). @deprecated Use CU_ASSERT_PTR_NOT_NULL_FATAL. */ +#define ASSERT_PTR_NOT_NULL(value) { if (NULL == (void*)(value)) { CU_assertImplementation(FALSE, __LINE__, ("ASSERT_PTR_NOT_NULL(" #value")"), __FILE__, "", FALSE); return; }} +/** Deprecated (version 1). @deprecated Use CU_ASSERT_STRING_EQUAL_FATAL. */ +#define ASSERT_STRING_EQUAL(actual, expected) { if (strcmp((const char*)actual, (const char*)expected)) { CU_assertImplementation(FALSE, __LINE__, ("ASSERT_STRING_EQUAL(" #actual "," #expected ")"), __FILE__, "", FALSE); return; }} +/** Deprecated (version 1). @deprecated Use CU_ASSERT_STRING_NOT_EQUAL_FATAL. */ +#define ASSERT_STRING_NOT_EQUAL(actual, expected) { if (!strcmp((const char*)actual, (const char*)expected)) { CU_assertImplementation(TRUE, __LINE__, ("ASSERT_STRING_NOT_EQUAL(" #actual "," #expected ")"), __FILE__, "", FALSE); return; }} +/** Deprecated (version 1). @deprecated Use CU_ASSERT_NSTRING_EQUAL_FATAL. */ +#define ASSERT_NSTRING_EQUAL(actual, expected, count) { if (strncmp((const char*)actual, (const char*)expected, (size_t)count)) { CU_assertImplementation(FALSE, __LINE__, ("ASSERT_NSTRING_EQUAL(" #actual "," #expected "," #count ")"), __FILE__, "", FALSE); return; }} +/** Deprecated (version 1). @deprecated Use CU_ASSERT_NSTRING_NOT_EQUAL_FATAL. */ +#define ASSERT_NSTRING_NOT_EQUAL(actual, expected, count) { if (!strncmp((const char*)actual, (const char*)expected, (size_t)count)) { CU_assertImplementation(TRUE, __LINE__, ("ASSERT_NSTRING_NOT_EQUAL(" #actual "," #expected "," #count ")"), __FILE__, "", FALSE); return; }} +/** Deprecated (version 1). @deprecated Use CU_ASSERT_DOUBLE_EQUAL_FATAL. */ +#define ASSERT_DOUBLE_EQUAL(actual, expected, granularity) { if ((fabs((double)actual - expected) > fabs((double)granularity))) { CU_assertImplementation(FALSE, __LINE__, ("ASSERT_DOUBLE_EQUAL(" #actual "," #expected "," #granularity ")"), __FILE__, "", FALSE); return; }} +/** Deprecated (version 1). @deprecated Use CU_ASSERT_DOUBLE_NOT_EQUAL_FATAL. */ +#define ASSERT_DOUBLE_NOT_EQUAL(actual, expected, granularity) { if ((fabs((double)actual - expected) <= fabs((double)granularity))) { CU_assertImplementation(TRUE, __LINE__, ("ASSERT_DOUBLE_NOT_EQUAL(" #actual "," #expected "," #granularity ")"), __FILE__, "", FALSE); return; }} +#endif /* USE_DEPRECATED_CUNIT_NAMES */ + +#endif /* CUNIT_CUNIT_H_SEEN */ + +/** @} */ diff --git a/pde-test-host/pde-test-host/include/CUnit_intl.h b/pde-test-host/pde-test-host/include/CUnit_intl.h new file mode 100755 index 0000000..813917b --- /dev/null +++ b/pde-test-host/pde-test-host/include/CUnit_intl.h @@ -0,0 +1,62 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2006 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 + */ + +/* + * Internationalization support + * + * 05-May-2006 Initial implementation. (JDS) + */ + +/** @file + * Internal CUnit header supporting internationalization of + * CUnit framework & interfaces. + */ +/** @addtogroup Framework + * @{ + */ + +#ifndef CUNIT_CUNIT_INTL_H_SEEN +#define CUNIT_CUNIT_INTL_H_SEEN + +/* activate these when source preparation is complete +#include +#ifndef _ +# define _(String) gettext (String) +#endif +#ifndef gettext_noop +# define gettext_noop(String) String +#endif +#ifndef N_ +# define N_(String) gettext_noop (String) +#endif +*/ + +/* deactivate these when source preparation is complete */ +#undef _ +#define _(String) (String) +#undef N_ +#define N_(String) String +#undef textdomain +#define textdomain(Domain) +#undef bindtextdomain +#define bindtextdomain(Package, Directory) + +#endif /* CUNIT_CUNIT_INTL_H_SEEN */ + +/** @} */ diff --git a/pde-test-host/pde-test-host/include/Console.h b/pde-test-host/pde-test-host/include/Console.h new file mode 100755 index 0000000..f5b3769 --- /dev/null +++ b/pde-test-host/pde-test-host/include/Console.h @@ -0,0 +1,60 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2001 Anil Kumar + * Copyright (C) 2004-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 + */ + +/* + * Contains Interface for console Run tests. + * + * Aug 2001 Initial implementation. (AK) + * + * 09/Aug/2001 Single interface to Console_run_tests. (AK) + * + * 20-Jul-2004 New interface, doxygen comments. (JDS) + */ + +/** @file + * Console interface with interactive output (user interface). + */ +/** @addtogroup Console + * @{ + */ + +#ifndef CUNIT_CONSOLE_H_SEEN +#define CUNIT_CONSOLE_H_SEEN + +#include "CUnit.h" +#include "TestDB.h" + +#ifdef __cplusplus +extern "C" { +#endif + +CU_EXPORT void CU_console_run_tests(void); +/**< Run registered CUnit tests using the console interface. */ + +#ifdef USE_DEPRECATED_CUNIT_NAMES +/** Deprecated (version 1). @deprecated Use CU_console_run_tests(). */ +#define console_run_tests() CU_console_run_tests() +#endif /* USE_DEPRECATED_CUNIT_NAMES */ + +#ifdef __cplusplus +} +#endif +#endif /* CUNIT_CONSOLE_H_SEEN */ +/** @} */ diff --git a/pde-test-host/pde-test-host/include/Makefile b/pde-test-host/pde-test-host/include/Makefile new file mode 100644 index 0000000..16e334a --- /dev/null +++ b/pde-test-host/pde-test-host/include/Makefile @@ -0,0 +1,22 @@ +# $Id: Makefile,v 1.2 Broadcom SDK $ +# $Copyright: (c) 2018 Broadcom. +# Broadcom Proprietary and Confidential. All rights reserved.$ +# +# Include standard Makefile configuration +# + +include ${SDK}/make/Make.config +include ${SDK}/make/Make.depend + +all:: + +install:: ${install_files} + +${install_files}:: + ${INSTALL} -d ${install_headers}/$(dir $@) + ${INSTALL} -m0644 -c $@ ${install_headers}/$(dir $@) + +clean:: + +distclean:: + $(RM) ${install_headers} diff --git a/pde-test-host/pde-test-host/include/MyMem.h b/pde-test-host/pde-test-host/include/MyMem.h new file mode 100755 index 0000000..88a7e62 --- /dev/null +++ b/pde-test-host/pde-test-host/include/MyMem.h @@ -0,0 +1,104 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2001 Anil Kumar + * Copyright (C) 2004-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 + */ + +/* + * Contains Memory Related Defines to use internal routines to detect Memory Leak + * in Debug Versions + * + * 18/Jun/2002 Memory Debug Functions. (AK) + * + * 17-Jul-2004 New interface for global function names. (JDS) + * + * 05-Sep-2004 Added internal test interface. (JDS) + */ + +/** @file + * Memory management functions (user interface). + * Two versions of memory allocation/deallocation are available. + * If compiled with MEMTRACE defined, CUnit keeps track of all + * system allocations & deallocations. The memory record can + * then be reported using CU_CREATE_MEMORY_REPORT. Otherwise, + * standard system memory allocation is used without tracing. + */ +/** @addtogroup Framework + * @{ + */ + +#ifndef CUNIT_MYMEM_H_SEEN +#define CUNIT_MYMEM_H_SEEN + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef MEMTRACE + void* CU_calloc(size_t nmemb, size_t size, unsigned int uiLine, const char* szFileName); + void* CU_malloc(size_t size, unsigned int uiLine, const char* szFileName); + void CU_free(void *ptr, unsigned int uiLine, const char* szFileName); + void* CU_realloc(void *ptr, size_t size, unsigned int uiLine, const char* szFileName); + CU_EXPORT void CU_dump_memory_usage(const char*); + + /** c-allocate with memory tracking. */ + #define CU_CALLOC(x, y) CU_calloc((x), (y), __LINE__, __FILE__) + /** m-allocate with memory tracking. */ + #define CU_MALLOC(x) CU_malloc((x), __LINE__, __FILE__) + /** Free with memory tracking. */ + #define CU_FREE(x) CU_free((x), __LINE__, __FILE__) + /** Reallocate with memory tracking. */ + #define CU_REALLOC(x, y) CU_realloc((x), (y), __LINE__, __FILE__) + /** Generate report on tracked memory. */ + #define CU_CREATE_MEMORY_REPORT(x) CU_dump_memory_usage((x)) + /** Generate report on tracked memory (old macro). */ + #define CU_DUMP_MEMORY_USAGE(x) CU_dump_memory_usage((x)) +#else /* MEMTRACE */ + /** Standard calloc() if MEMTRACE not defined. */ + #define CU_CALLOC(x, y) calloc((x), (y)) + /** Standard malloc() if MEMTRACE not defined. */ + #define CU_MALLOC(x) malloc((x)) + /** Standard free() if MEMTRACE not defined. */ + #define CU_FREE(x) free((x)) + /** Standard realloc() if MEMTRACE not defined. */ + #define CU_REALLOC(x, y) realloc((x), (y)) + /** No-op if MEMTRACE not defined. */ + #define CU_CREATE_MEMORY_REPORT(x) + /** No-op if MEMTRACE not defined. */ + #define CU_DUMP_MEMORY_USAGE(x) +#endif /* MEMTRACE */ + +#ifdef CUNIT_BUILD_TESTS +/** Disable memory allocation for testing purposes. */ +void test_cunit_deactivate_malloc(void); +/** Enable memory allocation for testing purposes. */ +void test_cunit_activate_malloc(void); +/** Retrieve number of memory events for a given pointer */ +unsigned int test_cunit_get_n_memevents(void* pLocation); +/** Retrieve number of allocations for a given pointer */ +unsigned int test_cunit_get_n_allocations(void* pLocation); +/** Retrieve number of deallocations for a given pointer */ +unsigned int test_cunit_get_n_deallocations(void* pLocation); + +void test_cunit_MyMem(void); +#endif /* CUNIT_BUILD_TESTS */ + +#ifdef __cplusplus +} +#endif +#endif /* CUNIT_MYMEM_H_SEEN */ +/** @} */ diff --git a/pde-test-host/pde-test-host/include/TestDB.h b/pde-test-host/pde-test-host/include/TestDB.h new file mode 100755 index 0000000..ec07f92 --- /dev/null +++ b/pde-test-host/pde-test-host/include/TestDB.h @@ -0,0 +1,914 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2001 Anil Kumar + * Copyright (C) 2004-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 + */ + +/* + * Contains all the Type Definitions and functions declarations + * for the CUnit test database maintenance. + * + * Aug 2001 Initial implementation. (AK) + * + * 09/Aug/2001 Added Preprocessor conditionals for the file. (AK) + * + * 24/aug/2001 Made the linked list from SLL to DLL(doubly linked list). (AK) + * + * 31-Aug-2004 Restructured to eliminate global variables error_number, + * g_pTestRegistry; new interface, support for deprecated + * version 1 interface, moved error handling code to + * CUError.[ch], moved test run counts and _TestResult out + * of TestRegistry to TestRun.h. (JDS) + * + * 01-Sep-2004 Added jmp_buf to CU_Test. (JDS) + * + * 05-Sep-2004 Added internal test interface. (JDS) + * + * 15-Apr-2006 Removed constraint that suites/tests be uniquely named. + * Added ability to turn individual tests/suites on or off. + * Moved doxygen comments for public API here to header. (JDS) + */ + +/** @file + * Management functions for tests, suites, and the test registry. + * Unit testing in CUnit follows the common structure of unit + * tests aggregated in suites, which are themselves aggregated + * in a test registry. This module provides functions and + * typedef's to support the creation, registration, and manipulation + * of test cases, suites, and the registry. + */ +/** @addtogroup Framework + * @{ + */ + +#ifndef CUNIT_TESTDB_H_SEEN +#define CUNIT_TESTDB_H_SEEN + +#include /* jmp_buf */ + +#include "CUnit.h" +#include "CUError.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*================================================================= + * Typedefs and Data Structures + *=================================================================*/ + +typedef int (*CU_InitializeFunc)(void); /**< Signature for suite initialization function. */ +typedef int (*CU_CleanupFunc)(void); /**< Signature for suite cleanup function. */ +typedef void (*CU_TestFunc)(void); /**< Signature for a testing function in a test case. */ + +/*----------------------------------------------------------------- + * CU_Test, CU_pTest + *-----------------------------------------------------------------*/ +/** CUnit test case data type. + * CU_Test is a double linked list of unit tests. Each test has + * a name, a callable test function, and a flag for whether the + * test is active and thus executed during a test run. A test + * also holds links to the next and previous tests in the list, + * as well as a jmp_buf reference for use in implementing fatal + * assertions.

+ * + * Generally, the linked list includes tests which are associated + * with each other in a CU_Suite. As a result, tests are run in + * the order in which they are added to a suite (see CU_add_test()). + *

+ * + * It is recommended that the name of each CU_Test in a suite have + * a unique name. Otherwise, only the first-registered test having + * a given name will be accessible by that name. There are no + * restrictions on the test function. This means that the same + * function could, in principle, be called more than once from + * different tests. + * + * @see CU_Suite + * @see CU_TestRegistry + */ +typedef struct CU_Test +{ + char* pName; /**< Test name. */ + CU_BOOL fActive; /**< Flag for whether test is executed during a run. */ + CU_TestFunc pTestFunc; /**< Pointer to the test function. */ + jmp_buf* pJumpBuf; /**< Jump buffer for setjmp/longjmp test abort mechanism. */ + + struct CU_Test* pNext; /**< Pointer to the next test in linked list. */ + struct CU_Test* pPrev; /**< Pointer to the previous test in linked list. */ + +} CU_Test; +typedef CU_Test* CU_pTest; /**< Pointer to a CUnit test case. */ + +/*----------------------------------------------------------------- + * CU_Suite, CU_pSuite + *-----------------------------------------------------------------*/ +/** CUnit suite data type. + * CU_Suite is a linked list of CU_Test containers. Each suite has + * a name, a count of registered unit tests, and a flag for whether + * the suite is active during test runs. It also holds pointers to + * optional initialization and cleanup functions. If non-NULL, these + * are called before and after running the suite's tests, respectively. + * In addition, the suite holds a pointer to the head of the linked + * list of associated CU_Test objects. Finally, pointers to the next + * and previous suites in the linked list are maintained.

+ * + * Generally, the linked list includes suites which are associated with + * each other in a CU_TestRegistry. As a result, suites are run in the + * order in which they are registered (see CU_add_suite()).

+ * + * It is recommended that name of each CU_Suite in a test registry have + * a unique name. Otherwise, only the first-registered suite having a + * given name will be accessible by name. There are no restrictions on + * the contained tests. This means that the same CU_Test could, in + * principle, be run more than once fron different suites. + * + * @see CU_Test + * @see CU_TestRegistry + */ +typedef struct CU_Suite +{ + char* pName; /**< Suite name. */ + CU_BOOL fActive; /**< Flag for whether suite is executed during a run. */ + CU_pTest pTest; /**< Pointer to the 1st test in the suite. */ + CU_InitializeFunc pInitializeFunc; /**< Pointer to the suite initialization function. */ + CU_CleanupFunc pCleanupFunc; /**< Pointer to the suite cleanup function. */ + + unsigned int uiNumberOfTests; /**< Number of tests in the suite. */ + struct CU_Suite* pNext; /**< Pointer to the next suite in linked list. */ + struct CU_Suite* pPrev; /**< Pointer to the previous suite in linked list. */ + +} CU_Suite; +typedef CU_Suite* CU_pSuite; /**< Pointer to a CUnit suite. */ + +/*----------------------------------------------------------------- + * CU_TestRegistry, CU_pTestRegistry + *-----------------------------------------------------------------*/ +/** CUnit test registry data type. + * CU_TestRegisty is the repository for suites containing unit tests. + * The test registry maintains a count of the number of CU_Suite + * objects contained in the registry, as well as a count of the total + * number of CU_Test objects associated with those suites. It also + * holds a pointer to the head of the linked list of CU_Suite objects. + *

+ * + * With this structure, the user will normally add suites implictly to + * the internal test registry using CU_add_suite(), and then add tests + * to each suite using CU_add_test(). Test runs are then initiated + * using one of the appropriate functions in TestRun.c via one of the + * user interfaces.

+ * + * Automatic creation and destruction of the internal registry and its + * objects is available using CU_initialize_registry() and + * CU_cleanup_registry(), respectively. For internal and testing + * purposes, the internal registry can be retrieved and assigned. + * Functions are also provided for creating and destroying independent + * registries.

+ * + * Note that earlier versions of CUnit also contained a pointer to a + * linked list of CU_FailureRecord objects (termed _TestResults). + * This has been removed from theregistry and relocated to TestRun.c. + * + * @see CU_Test + * @see CU_Suite + * @see CU_initialize_registry() + * @see CU_cleanup_registry() + * @see CU_get_registry() + * @see CU_set_registry() + * @see CU_create_new_registry() + * @see CU_destroy_existing_registry() + */ +typedef struct CU_TestRegistry +{ +#ifdef USE_DEPRECATED_CUNIT_NAMES + /** Union to support v1.1-1 member name. */ + union { + unsigned int uiNumberOfSuites; /**< Number of suites in the test registry. */ + unsigned int uiNumberOfGroups; /**< Deprecated (version 1). @deprecated Use uiNumberOfSuites. */ + }; + unsigned int uiNumberOfTests; /**< Number of tests in the test registry. */ + /** Union to support v1.1-1 member name. */ + union { + CU_pSuite pSuite; /**< Pointer to the 1st suite in the test registry. */ + CU_pSuite pGroup; /**< Deprecated (version 1). @deprecated Use pSuite. */ + }; +#else + unsigned int uiNumberOfSuites; /**< Number of registered suites in the registry. */ + unsigned int uiNumberOfTests; /**< Total number of registered tests in the registry. */ + CU_pSuite pSuite; /**< Pointer to the 1st suite in the test registry. */ +#endif +} CU_TestRegistry; +typedef CU_TestRegistry* CU_pTestRegistry; /**< Pointer to a CUnit test registry. */ + +/*================================================================= + * Public interface functions + *=================================================================*/ + +CU_EXPORT +CU_ErrorCode CU_initialize_registry(void); +/**< + * Initializes the framework test registry. + * Any existing registry is freed, including all stored suites + * and associated tests. It is not necessary to explicitly call + * CU_cleanup_registry() before reinitializing the framework. + * The most recent stored test results are also cleared.

+ * + * This function must not be called during a test run (checked + * by assertion) + * + * @return CUE_NOMEMORY if memory for the new registry cannot + * be allocated, CUE_SUCCESS otherwise. + * @see CU_cleanup_registry + * @see CU_get_registry + * @see CU_set_registry + * @see CU_registry_initialized + */ + +CU_EXPORT +void CU_cleanup_registry(void); +/**< + * Clears the test registry. + * The active test registry is freed, including all stored suites + * and associated tests. The most recent stored test results are + * also cleared. After calling this function, CUnit suites cannot + * be added until CU_initialize_registry() or CU_set_registry() is + * called. Further, any pointers to suites or test cases held by + * the user will be invalidated by calling this function.

+ * + * This function may be called multiple times without generating + * an error condition. However, this function must not be + * called during a test run (checked by assertion)

. + * + * @see CU_initialize_registry + * @see CU_get_registry + * @see CU_set_registry + */ + +CU_EXPORT CU_BOOL CU_registry_initialized(void); +/**< + * Checks whether the test registry has been initialized. + * + * @return CU_TRUE if the registry has been initialized, + * CU_FALSE otherwise. + * @see CU_initialize_registry + * @see CU_cleanup_registry + */ + +CU_EXPORT +CU_pSuite CU_add_suite(const char *strName, + CU_InitializeFunc pInit, + CU_CleanupFunc pClean); +/**< + * Creates a new test suite and adds it to the test registry. + * This function creates a new test suite having the specified + * name and initialization/cleanup functions and adds it to the + * test registry. The new suite will be active and able to be + * executed during a test run. The test registry must be + * initialized before calling this function (checked by assertion). + * pInit and pClean may be NULL, in which case no corresponding + * initialization of cleanup function will be called when the suite + * is run. strName may be empty ("") but may not be NULL.

+ * + * The return value is a pointer to the newly-created suite, or + * NULL if there was a problem with the suite creation or addition. + * An error code is also set for the framework. Note that if the + * name specified for the new suite is a duplicate, the suite will + * be created and added but the error code will be set to CUE_DUP_SUITE. + * The duplicate suite will not be accessible by name.

+ * + * NOTE - the CU_pSuite pointer returned should NOT BE FREED BY + * THE USER. The suite is freed by the CUnit system when + * CU_cleanup_registry() is called. This function must not + * be called during a test run (checked by assertion).

+ * + * CU_add_suite() sets the following error codes: + * - CUE_SUCCESS if no errors occurred. + * - CUE_NOREGISTRY if the registry has not been initialized. + * - CUE_NO_SUITENAME if strName is NULL. + * - CUE_DUP_SUITE if a suite having strName is already registered. + * - CUE_NOMEMORY if a memory allocation failed. + * + * @param strName Name for the new test suite (non-NULL). + * @param pInit Initialization function to call before running suite. + * @param pClean Cleanup function to call after running suite. + * @return A pointer to the newly-created suite (NULL if creation failed) + */ + +CU_EXPORT +CU_ErrorCode CU_set_suite_active(CU_pSuite pSuite, CU_BOOL fNewActive); +/**< + * Activates or deactivates a suite. + * Only activated suites can be executed during a test run. + * By default a suite is active upon creation, but can be deactivated + * by passing it along with CU_FALSE to this function. The suite + * can be reactivated by passing it along with CU_TRUE. The current + * value of the active flag is available as pSuite->fActive. If pSuite + * is NULL then error code CUE_NOSUITE is returned. + * + * @param pSuite Pointer to the suite to modify (non-NULL). + * @param fNewActive If CU_TRUE then the suite will be activated; + * if CU_FALSE it will be deactivated. + * @return Returns CUE_NOSUITE if pSuite is NULL, CUE_SUCCESS if all is well. + */ + +CU_EXPORT +CU_ErrorCode CU_set_suite_name(CU_pSuite pSuite, const char *strNewName); +/**< + * Modifies the name of a suite. + * This function allows the name associated with a suite to + * be changed. It is not recommended that a suite name be changed, + * nor should it be necessary under most circumstances. However, + * this function is provided for those clients who need to change + * a suite's name. The current value of the suite's name + * is available as pSuite->pName. CUE_SUCCESS is returned if the + * function succeeds in changing the name. CUE_NOSUITE is returned if + * pSuite is NULL, and CUE_NO_SUITENAME if strNewName is NULL. + * + * @param pSuite Pointer to the suite to modify (non-NULL). + * @param strNewName Pointer to string containing new suite name (non-NULL). + * @return Returns CUE_NOSUITE if pSuite is NULL, CUE_NO_SUITENAME if + * strNewName is NULL, and CUE_SUCCESS if all is well. + */ + +CU_EXPORT +CU_ErrorCode CU_set_suite_initfunc(CU_pSuite pSuite, CU_InitializeFunc pNewInit); +/**< + * Modifies the initialization function of a suite. + * This function allows the initialization function associated with + * a suite to be changed. This is neither recommended nor should it + * be necessary under most circumstances. However, this function is + * provided for those clients who need to change the function. The + * current value of the function is available as pSuite->pInitializeFunc. + * CUE_SUCCESS is returned if the function succeeds, or CUE_NOSUITE if + * pSuite is NULL. pNewInit may be NULL, which indicates the suite has + * no initialization function. + * + * @param pSuite Pointer to the suite to modify (non-NULL). + * @param pNewInit Pointer to function to use to initialize suite. + * @return Returns CUE_NOSUITE if pSuite is NULL, and CUE_SUCCESS if + * all is well. + */ + +CU_EXPORT +CU_ErrorCode CU_set_suite_cleanupfunc(CU_pSuite pSuite, CU_CleanupFunc pNewClean); +/**< + * Modifies the cleanup function of a suite. + * This function allows the cleanup function associated with a suite to + * be changed. This is neither recommended nor should it be necessary + * under most circumstances. However, this function is provided for those + * clients who need to change the function. The current value of the + * function is available as pSuite->pCleanupFunc. CUE_SUCCESS is returned + * if the function succeeds, or CUE_NOSUITE if pSuite is NULL. pNewClean + * may be NULL, which indicates the suite has no cleanup function. + * + * @param pSuite Pointer to the suite to modify (non-NULL). + * @param pNewClean Pointer to function to use to clean up suite. + * @return Returns CUE_NOSUITE if pSuite is NULL, and CUE_SUCCESS if + * all is well. + */ + +CU_EXPORT +CU_pSuite CU_get_suite(const char* strName); +/**< + * Retrieves the suite having the specified name. + * Searches the active test registry and returns a pointer to the 1st + * suite found. NULL is returned if no suite having the specified name + * is found. In addition, the framework error state is set to CUE_NOREGISTRY + * if the registry is not initialized or to CUE_NO_SUITENAME if strName is NULL. + * If the return value is NULL and framework error state is CUE_SUCCESS, then + * the search simply failed to find the specified name. + * Use CU_get_suite_at_pos() to retrieve a suite by position rather than name. + * + * @param strName The name of the suite to search for (non-NULL). + * @return Returns a pointer to the suite, or NULL if not found or an error occurred. + * @see CU_get_suite_at_pos() + */ + +CU_EXPORT +CU_pSuite CU_get_suite_at_pos(unsigned int pos); +/**< + * Retrieves the suite at the specified position. + * Iterates the active test registry and returns a pointer to the suite at + * position pos. pos is a 1-based index having valid values + * [1 .. CU_get_registry()->uiNumberOfSuites] and corresponds to the order in + * which suites were registered. If pos is invalid or an error occurs, 0 is + * returned. In addition, the framework error state is set to CUE_NOREGISTRY if + * the registry is not initialized, or CUE_SUCCESS if pos was invalid. Use + * CU_get_suite() to retrieve a suite by name rather than position. + * + * @param pos The 1-based position of the suite to fetch. + * @return Returns a pointer to the suite, or 0 if not found or an error occurred. + * @see CU_get_suite() + */ + +CU_EXPORT +unsigned int CU_get_suite_pos(CU_pSuite pSuite); +/**< + * Looks up the position of the specified suite. + * The position is a 1-based index of suites in the active test registry which + * corresponds to the order in which suites were registered. If pSuite is not + * found or an error occurs, 0 is returned. In addition, the framework error + * state is set to CUE_NOREGISTRY if the registry is not initialized, or + * CUE_NOSUITE if pSuite is NULL. The returned position may be used to retrieve + * the suite using CU_get_suite_by_pos(). + * + * @param pSuite Pointer to the suite to find (non-NULL). + * @return Returns the 1-based position of pSuite in the registry, or NULL if + * not found or an error occurred. + * @see CU_get_suite_by_pos() + * @see CU_get_suite_pos_by_name() + */ + +CU_EXPORT +unsigned int CU_get_suite_pos_by_name(const char* strName); +/**< + * Looks up the position of the suite having the specified name. + * The position is a 1-based index of suites in the active test registry which + * corresponds to the order in which suites were registered. If no suite has the + * specified name or an error occurs, 0 is returned. In addition, the framework error + * state is set to CUE_NOREGISTRY if the registry is not initialized, or + * CUE_NO_SUITENAME if strName is NULL. The search ends at the 1st suite found having + * name strName. The returned position may be used to retrieve the suite using + * CU_get_suite_by_pos(). + * + * @param strName Name of the suite to find (non-NULL). + * @return Returns the 1-based position of pSuite in the registry, or NULL if + * not found or an error occurred. + * @see CU_get_suite_by_pos() + * @see CU_get_suite_pos_by_name() + */ + +CU_EXPORT +CU_pTest CU_add_test(CU_pSuite pSuite, const char* strName, CU_TestFunc pTestFunc); +/**< + * This function creates a new test having the specified name + * and function, and adds it to the specified suite. The new test + * is active and able to be executed during a test run. At present, + * there is no mechanism for creating a test case independent of a + * suite. Neither pSuite, strName, nor pTestFunc may be NULL. + * + * The return value is a pointer to the newly-created test, or + * NULL if there was a problem with the test creation or addition. + * An error code is also set for the framework. Note that if the + * name specified for the new test is a duplicate within pSuite, + * the test will be created and added but the error code will be + * set to CUE_DUP_TEST. The duplicate test will not be accessible + * by name.

+ * + * NOTE - the CU_pTest pointer returned should NOT BE FREED BY + * THE USER. The test is freed by the CUnit system when + * CU_cleanup_registry() is called. This function must not + * be called during a test run (checked by assertion).

+ + * CU_add_test() sets the following error codes: + * - CUE_SUCCESS if no errors occurred. + * - CUE_NOREGISTRY if the registry has not been initialized. + * - CUE_NOSUITE if pSuite is NULL. + * - CUE_NO_TESTNAME if strName is NULL. + * - CUE_NOTEST if pTestFunc is NULL. + * - CUE_DUP_TEST if a test having strName is already registered to pSuite. + * - CUE_NOMEMORY if a memory allocation failed.

+ * + * @param pSuite Test suite to which to add new test (non-NULL). + * @param strName Name for the new test case (non-NULL). + * @param pTest Function to call when running the test (non-NULL). + * @return A pointer to the newly-created test (NULL if creation failed) + */ + +CU_EXPORT +CU_ErrorCode CU_set_test_active(CU_pTest pTest, CU_BOOL fNewActive); +/**< + * Activates or deactivates a specific test. + * Only activated tests can be executed during a test run. + * By default a test is active upon creation, but can be deactvated + * by passing it along with CU_FALSE to this function. The test + * can be reactivated by passing it along with CU_TRUE. + * The current value of the active flag is available as pTest->fActive. + * If pTest is NULL then error code CUE_NOTEST is returned. Otherwise + * CUE_SUCCESS is returned. + * + * @param pTest Pointer to the test to modify (non-NULL). + * @param fNewActive If CU_TRUE then test will be activated; + * if CU_FALSE it will be deactivated. + * @return Returns CUE_NOTEST if pTest is NULL, CUE_SUCCESS if all is well. +*/ + +CU_EXPORT +CU_ErrorCode CU_set_test_name(CU_pTest pTest, const char *strNewName); +/**< + * Modifies the name of a test. + * This function allows the name associated with a test to + * be changed. It is not recommended that a test name be changed, + * nor should it be necessary under most circumstances. However, + * this function is provided for those clients who need to change + * a test's name. The current value of the test's name is + * available as pTest->pName. CUE_SUCCESS is returned if the + * function succeeds in changing the name. CUE_NOTEST is returned if + * pTest is NULL, and CUE_NO_TESTNAME if strNewName is NULL. + * + * @param pTest Pointer to the test to modify (non-NULL). + * @param strNewName Pointer to string containing new test name (non-NULL). + * @return Returns CUE_NOTEST if pTest is NULL, CUE_NO_TESTNAME if + * strNewName is NULL, and CUE_SUCCESS if all is well. + */ + +CU_EXPORT +CU_ErrorCode CU_set_test_func(CU_pTest pTest, CU_TestFunc pNewFunc); +/**< + * Modifies the test function of a test. + * This function allows the test function associated with a test to be + * changed. This is neither recommended nor should it be necessary under + * most circumstances. However, this function is provided for those + * clients who need to change the test function. The current value of + * the test function is available as pTest->pTestFunc. CUE_SUCCESS is + * returned if the function succeeds, or CUE_NOTEST if either pTest or + * pNewFunc is NULL. + * + * @param pTest Pointer to the test to modify (non-NULL). + * @param pNewFunc Pointer to function to use for test function (non-NULL). + * @return Returns CUE_NOTEST if pTest or pNewFunc is NULL, and CUE_SUCCESS + * if all is well. + */ + +CU_EXPORT +CU_pTest CU_get_test(CU_pSuite pSuite, const char *strName); +/**< + * Retrieves the test having the specified name. + * Searches pSuite and returns a pointer to the 1st test found named strName. + * NULL is returned if no test having the specified name is found in pSuite. + * In addition, the framework error state is set as follows: + * - CUE_NOREGISTRY if the registry is not initialized + * - CUE_NOSUITE if pSuite is NULL + * - CUE_NO_TESTNAME if strName is NULL. + * + * If the return value is NULL and framework error state is CUE_SUCCESS, then + * the search simply failed to find the specified name. Use CU_get_test_at_pos() + * to retrieve a test by position rather than name. + * + * @param pSuite Pointer to the suite to search (non-NULL). + * @param strName The name of the test to search for (non-NULL). + * @return Returns a pointer to the test, or NULL if not found or an error occurred. + * @see CU_get_test_at_pos() + */ + +CU_EXPORT +CU_pTest CU_get_test_at_pos(CU_pSuite pSuite, unsigned int pos); +/**< + * Retrieves the test at the specified position in pSuite. + * Iterates the tests registered in pSuite and returns a pointer to the + * test at position pos. pos is a 1-based index having valid values + * [1 .. pSuite->uiNumberOfTests] and corresponds to the order in + * which tests were added to pSuite. If pos is invalid or an error occurs, 0 is + * returned. In addition, the framework error state is set as follows: + * - CUE_NOREGISTRY if the registry is not initialized + * - CUE_NOSUITE if pSuite is NULL + * Use CU_get_test() to retrieve a test by name rather than position. + * + * @param pSuite Pointer to the suite to search (non-NULL). + * @param pos The 1-based position of the test to fetch. + * @return Returns a pointer to the test, or 0 if not found or an error occurred. + * @see CU_get_test() + */ + +CU_EXPORT +unsigned int CU_get_test_pos(CU_pSuite pSuite, CU_pTest pTest); +/**< + * Looks up the position of the specified test in pSuite. + * The position is a 1-based index of tests in pSuite which corresponds to the + * order in which tests were added. If pTest is not found or an error occurs, + * 0 is returned. In addition, the framework error state is set as follows: + * - CUE_NOREGISTRY if the registry is not initialized + * - CUE_NOSUITE if pSuite is NULL + * - CUE_NOTEST if pTest is NULL + * + * The returned position may be used to retrieve the test using CU_get_test_by_pos(). + * + * @param pSuite Pointer to the suite to search (non-NULL). + * @param pTest Pointer to the test to find (non-NULL). + * @return Returns the 1-based position of pTest in pSuite, or NULL if + * not found or an error occurred. + * @see CU_get_test_by_pos() + * @see CU_get_test_pos_by_name() + */ + +CU_EXPORT +unsigned int CU_get_test_pos_by_name(CU_pSuite pSuite, const char *strName); +/**< + * Looks up the position of the test having the specified name in pSuite. + * The position is a 1-based index of tests in pSuite which corresponds to the order + * in which tests were added. If no test has the specified name or an error occurs, + * 0 is returned. In addition, the framework error state is set as follows: + * - CUE_NOREGISTRY if the registry is not initialized + * - CUE_NOSUITE if pSuite is NULL + * - CUE_NO_TESTNAME if strName is NULL + * The search ends at the 1st test found having name strName. The returned position + * may be used to retrieve the suite using CU_get_test_by_pos(). + * + * @param pSuite Pointer to the suite to search (non-NULL). + * @param strName Name of the test to find (non-NULL). + * @return Returns the 1-based position of pTest in pSuite, or NULL if + * not found or an error occurred. + * @see CU_get_test_by_pos() + * @see CU_get_test_pos_by_name() + */ + +#define CU_ADD_TEST(suite, test) (CU_add_test(suite, #test, (CU_TestFunc)test)) +/**< Shortcut macro for adding a test to a suite. */ + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +/* This section is based conceptually on code + * Copyright (C) 2004 Aurema Pty Ltd. + * + * 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 + * + * Derived from code contributed by K. Cheung and Aurema Pty Ltd. (thanks!) + * test_case_t, test_group_t, test_suite_t + */ + +/** + * Test case parameters structure. + * This data type is provided to assist CUnit users manage collections of + * tests and suites. It is intended to be used to build arrays of test case + * parameters that can be then be referred to in a CU_suite_info_t variable. + */ +typedef struct CU_TestInfo { + char *pName; /**< Test name. */ + CU_TestFunc pTestFunc; /**< Test function. */ +} CU_TestInfo; +typedef CU_TestInfo* CU_pTestInfo; /**< Pointer to CU_TestInfo type. */ + +/** + * Suite parameters. + * This data type is provided to assist CUnit users manage collections of + * tests and suites. It is intended to be used to build arrays of suite + * parameters that can be passed to a bulk registration function such as + * CU_register_suite() or CU_register_suites(). + */ +typedef struct CU_SuiteInfo { + char *pName; /**< Suite name. */ + CU_InitializeFunc pInitFunc; /**< Suite initialization function. */ + CU_CleanupFunc pCleanupFunc; /**< Suite cleanup function */ + CU_TestInfo *pTests; /**< Test case array - must be NULL terminated. */ +} CU_SuiteInfo; +typedef CU_SuiteInfo* CU_pSuiteInfo; /**< Pointer to CU_SuiteInfo type. */ + +#define CU_TEST_INFO_NULL { NULL, NULL } +/**< NULL CU_test_info_t to terminate arrays of tests. */ +#define CU_SUITE_INFO_NULL { NULL, NULL, NULL, NULL } +/**< NULL CU_suite_info_t to terminate arrays of suites. */ + + +CU_EXPORT CU_ErrorCode CU_register_suites(CU_SuiteInfo suite_info[]); +/**< + * Registers the suites in a single CU_SuiteInfo array. + * Multiple arrays can be registered using CU_register_nsuites(). + * + * @param suite_info NULL-terminated array of CU_SuiteInfo items to register. + * @return A CU_ErrorCode indicating the error status. + * @see CU_register_suites() + */ +CU_EXPORT CU_ErrorCode CU_register_nsuites(int suite_count, ...); +/**< + * Registers multiple suite arrays in CU_SuiteInfo format. + * The function accepts a variable number of suite arrays to be registered. + * The number of arrays is indicated by the value of the 1st argument, + * suite_count. Each suite in each array is registered with the CUnit test + * registry, along with all of the associated tests. + * + * @param suite_count The number of CU_SuiteInfo* arguments to follow. + * @param ... suite_count number of CU_SuiteInfo* arguments. NULLs are ignored. + * @return A CU_ErrorCode indicating the error status. + * @see CU_register_suites() + */ + +#ifdef USE_DEPRECATED_CUNIT_NAMES +typedef CU_TestInfo test_case_t; /**< Deprecated (version 1). @deprecated Use CU_TestInfo. */ +typedef CU_SuiteInfo test_group_t; /**< Deprecated (version 1). @deprecated Use CU_SuiteInfo. */ + +/** Deprecated (version 1). @deprecated Use CU_SuiteInfo and CU_TestInfo. */ +typedef struct test_suite { + char *name; /**< Suite name. Currently not used. */ + test_group_t *groups; /**< Test groups. This must be a NULL terminated array. */ +} test_suite_t; + +/** Deprecated (version 1). @deprecated Use CU_TEST_INFO_NULL. */ +#define TEST_CASE_NULL { NULL, NULL } +/** Deprecated (version 1). @deprecated Use CU_TEST_GROUP_NULL. */ +#define TEST_GROUP_NULL { NULL, NULL, NULL, NULL } + +/** Deprecated (version 1). @deprecated Use CU_register_suites(). */ +#define test_group_register(tg) CU_register_suites(tg) + +/** Deprecated (version 1). @deprecated Use CU_SuiteInfo and CU_register_suites(). */ +CU_EXPORT int test_suite_register(test_suite_t *ts) +{ + test_group_t *tg; + int error; + + for (tg = ts->groups; tg->pName; tg++) + if ((error = CU_register_suites(tg)) != CUE_SUCCESS) + return error; + + return CUE_SUCCESS; +} +#endif /* USE_DEPRECATED_CUNIT_NAMES */ +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +#ifdef USE_DEPRECATED_CUNIT_NAMES +typedef CU_InitializeFunc InitializeFunc; /**< Deprecated (version 1). @deprecated Use CU_InitializeFunc. */ +typedef CU_CleanupFunc CleanupFunc; /**< Deprecated (version 1). @deprecated Use CU_CleanupFunc. */ +typedef CU_TestFunc TestFunc; /**< Deprecated (version 1). @deprecated Use CU_TestFunc. */ + +typedef CU_Test _TestCase; /**< Deprecated (version 1). @deprecated Use CU_Test. */ +typedef CU_pTest PTestCase; /**< Deprecated (version 1). @deprecated Use CU_pTest. */ + +typedef CU_Suite _TestGroup; /**< Deprecated (version 1). @deprecated Use CU_Suite. */ +typedef CU_pSuite PTestGroup; /**< Deprecated (version 1). @deprecated Use CU_pSuite. */ + +typedef CU_TestRegistry _TestRegistry; /**< Deprecated (version 1). @deprecated Use CU_TestRegistry. */ +typedef CU_pTestRegistry PTestRegistry; /**< Deprecated (version 1). @deprecated Use CU_pTestRegistry. */ + +/* Public interface functions */ +/** Deprecated (version 1). @deprecated Use CU_initialize_registry(). */ +#define initialize_registry() CU_initialize_registry() +/** Deprecated (version 1). @deprecated Use CU_cleanup_registry(). */ +#define cleanup_registry() CU_cleanup_registry() +/** Deprecated (version 1). @deprecated Use CU_add_suite(). */ +#define add_test_group(name, init, clean) CU_add_suite(name, init, clean) +/** Deprecated (version 1). @deprecated Use CU_add_test(). */ +#define add_test_case(group, name, test) CU_add_test(group, name, test) + +/* private internal CUnit testing functions */ +/** Deprecated (version 1). @deprecated Use CU_get_registry(). */ +#define get_registry() CU_get_registry() +/** Deprecated (version 1). @deprecated Use CU_set_registry(). */ +#define set_registry(reg) CU_set_registry((reg)) + +/** Deprecated (version 1). @deprecated Use CU_get_suite_by_name(). */ +#define get_group_by_name(group, reg) CU_get_suite_by_name(group, reg) +/** Deprecated (version 1). @deprecated Use CU_get_test_by_name(). */ +#define get_test_by_name(test, group) CU_get_test_by_name(test, group) + +/** Deprecated (version 1). @deprecated Use ADD_TEST_TO_SUITE. */ +#define ADD_TEST_TO_GROUP(group, test) (CU_add_test(group, #test, (CU_TestFunc)test)) +#endif /* USE_DEPRECATED_CUNIT_NAMES */ + +/*================================================================= + * Internal CUnit system functions. + * Should not be routinely called by users. + *=================================================================*/ + +CU_EXPORT CU_pTestRegistry CU_get_registry(void); +/**< + * Retrieves a pointer to the current test registry. + * Returns NULL if the registry has not been initialized using + * CU_initialize_registry(). Directly accessing the registry + * should not be necessary for most users. This function is + * provided primarily for internal and testing purposes. + * + * @return A pointer to the current registry (NULL if uninitialized). + * @see CU_initialize_registry + * @see CU_set_registry + */ + +CU_EXPORT CU_pTestRegistry CU_set_registry(CU_pTestRegistry pTestRegistry); +/**< + * Sets the registry to an existing CU_pTestRegistry instance. + * A pointer to the original registry is returned. Note that the + * original registry is not freed, and it becomes the caller's + * responsibility to do so. Directly accessing the registry + * should not be necessary for most users. This function is + * provided primarily for internal and testing purposes.

+ * + * This function must not be called during a test run (checked + * by assertion). + * + * @return A pointer to the original registry that was replaced. + * @see CU_initialize_registry + * @see CU_cleanup_registry + * @see CU_get_registry + */ + +CU_EXPORT CU_pTestRegistry CU_create_new_registry(void); +/**< + * Creates and initializes a new test registry. + * Returns a pointer to a new, initialized registry (NULL if memory could + * not be allocated). It is the caller's responsibility to destroy and free + * the new registry (unless it is made the active test registry using + * CU_set_registry()). + */ + +CU_EXPORT +void CU_destroy_existing_registry(CU_pTestRegistry* ppRegistry); +/**< + * Destroys and frees all memory for an existing test registry. + * The active test registry is destroyed by the CUnit system in + * CU_cleanup_registry(), so only call this function on registries created + * or held independently of the internal CUnit system.

+ * + * Once a registry is made the active test registry using CU_set_registry(), + * its destruction will be handled by the framework. ppRegistry may not be + * NULL (checked by assertion), but *ppRegistry can be NULL (in which case the + * function has no effect). Note that *ppRegistry will be set to NULL on return. + * + * @param ppRegistry Address of a pointer to the registry to destroy (non-NULL). + */ + +CU_EXPORT +CU_pSuite CU_get_suite_by_name(const char *szSuiteName, CU_pTestRegistry pRegistry); +/**< + * Retrieves a pointer to the suite having the specified name. + * Scans the pRegistry and returns a pointer to the first suite located + * having the specified name. Neither szSuiteName nor pRegistry may be + * NULL (checked by assertion). Clients should normally use CU_get_suite() + * instead, which automatically searches the active test registry. + * + * @param szSuiteName The name of the suite to locate (non-NULL). + * @param pRegistry The registry to scan (non-NULL). + * @return Pointer to the first suite having the specified name, + * NULL if not found. + * @see CU_get_suite() + */ + +CU_EXPORT +CU_pSuite CU_get_suite_by_index(unsigned int index, CU_pTestRegistry pRegistry); +/**< + * Retrieves a pointer to the suite at the specified (1-based) index. + * Iterates pRegistry and returns a pointer to the suite located at the + * specified index. pRegistry may not be NULL (checked by assertion). + * Clients should normally use CU_get_suite_at_pos() instead, which + * automatically searches the active test registry. + * + * @param index The 1-based index of the suite to find. + * @param pRegistry The registry to scan (non-NULL). + * @return Pointer to the suite at the specified index, or + * NULL if index is invalid. + * @see CU_get_suite_at_pos() + */ + +CU_EXPORT +CU_pTest CU_get_test_by_name(const char* szTestName, CU_pSuite pSuite); +/**< + * Retrieves a pointer to the test case in pSuite having the specified name. + * The first test case in pSuite having the specified name is returned, or + * NULL if not found. Neither szSuiteName nor pSuite may be NULL (checked + * by assertion). Clients should normally use CU_get_test() instead. + * + * @param szTestName The name of the test case to locate (non-NULL). + * @param pSuite The suite to scan (non-NULL). + * @return Pointer to the first test case having the specified name, + * NULL if not found. + * @see CU_get_test() + */ + +CU_EXPORT +CU_pTest CU_get_test_by_index(unsigned int index, CU_pSuite pSuite); +/**< + * Retrieves a pointer to the test at the specified (1-based) index. + * Iterates pSuite and returns a pointer to the test located at the + * specified index. pSuite may not be NULL (checked by assertion). + * Clients should normally use CU_get_test_at_pos() instead, which + * automatically searches the active test registry. + * + * @param index The 1-based index of the test to find. + * @param pRegistry The registry to scan (non-NULL). + * @return Pointer to the test at the specified index, or + * NULL if index is invalid. + * @see CU_get_test_at_pos() + */ + +#ifdef CUNIT_BUILD_TESTS +void test_cunit_TestDB(void); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* CUNIT_TESTDB_H_SEEN */ +/** @} */ diff --git a/pde-test-host/pde-test-host/include/TestRun.h b/pde-test-host/pde-test-host/include/TestRun.h new file mode 100755 index 0000000..51072f4 --- /dev/null +++ b/pde-test-host/pde-test-host/include/TestRun.h @@ -0,0 +1,444 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2001 Anil Kumar + * Copyright (C) 2004-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 + */ + +/* + * Contains Interface to Run tests. + * + * Aug 2001 Initial implementation. (AK) + * + * 09/Aug/2001 Contains generic run tests interface which can be used + * for any type of frontend interface framework. (AK) + * + * 24/Nov/2001 Added Handler for Group Initialization failure condition. (AK) + * + * 05-Aug-2004 New interface. Since these should be internal functions, + * no support for deprecated version 1 names provided now, + * eliminated global variables for current test & suite, + * moved (renamed) _TestResult here from TestDB.h. (JDS) + * + * 05-Sep-2004 Added internal test interface. (JDS) + * + * 23-Apr-2006 Moved doxygen comments into header. + * Added type marker to CU_FailureRecord. + * Added support for tracking inactive suites/tests. (JDS) + * + * 08-May-2006 Moved CU_print_run_results() functionality from + * console/basic test complete handler. (JDS) + * + * 24-May-2006 Added callbacks for suite start and complete events. + * Added tracking/reported of elapsed time. (JDS) + */ + +/** @file + * Test run management functions (user interface). + * The TestRun module implements functions supporting the running + * of tests elements (suites and tests). This includes functions for + * running suites and tests, retrieving the number of tests/suites run, + * and managing callbacks during the run process.

+ * + * The callback mechanism works as follows. The CUnit runtime system + * supports the registering and calling of functions at the start and end + * of each test, when all tests are complete, and when a suite + * initialialization function returns an error. This allows clients to + * perform actions associated with these events such as output formatting + * and reporting. + */ +/** @addtogroup Framework + * @{ + */ + +#ifndef CUNIT_TESTRUN_H_SEEN +#define CUNIT_TESTRUN_H_SEEN + +#include "CUnit.h" +#include "CUError.h" +#include "TestDB.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Types of failures occurring during test runs. */ +typedef enum CU_FailureTypes +{ + CUF_SuiteInactive = 1, /**< Inactive suite was run. */ + CUF_SuiteInitFailed, /**< Suite initialization function failed. */ + CUF_SuiteCleanupFailed, /**< Suite cleanup function failed. */ + CUF_TestInactive, /**< Inactive test was run. */ + CUF_AssertFailed /**< CUnit assertion failed during test run. */ +} CU_FailureType; /**< Failure type. */ + +/* CU_FailureRecord type definition. */ +/** Data type for holding assertion failure information (linked list). */ +typedef struct CU_FailureRecord +{ + CU_FailureType type; /**< Failure type. */ + unsigned int uiLineNumber; /**< Line number of failure. */ + char* strFileName; /**< Name of file where failure occurred. */ + char* strCondition; /**< Test condition which failed. */ + CU_pTest pTest; /**< Test containing failure. */ + CU_pSuite pSuite; /**< Suite containing test having failure. */ + + struct CU_FailureRecord* pNext; /**< Pointer to next record in linked list. */ + struct CU_FailureRecord* pPrev; /**< Pointer to previous record in linked list. */ + +} CU_FailureRecord; +typedef CU_FailureRecord* CU_pFailureRecord; /**< Pointer to CU_FailureRecord. */ + +/* CU_RunSummary type definition. */ +/** Data type for holding statistics and assertion failures for a test run. */ +typedef struct CU_RunSummary +{ + unsigned int nSuitesRun; /**< Number of suites completed during run. */ + unsigned int nSuitesFailed; /**< Number of suites for which initialization failed. */ + unsigned int nSuitesInactive; /**< Number of suites which were inactive. */ + unsigned int nTestsRun; /**< Number of tests completed during run. */ + unsigned int nTestsFailed; /**< Number of tests containing failed assertions. */ + unsigned int nTestsInactive; /**< Number of tests which were inactive (in active suites). */ + unsigned int nAsserts; /**< Number of assertions tested during run. */ + unsigned int nAssertsFailed; /**< Number of failed assertions. */ + unsigned int nFailureRecords; /**< Number of failure records generated. */ + double ElapsedTime; /**< Elapsed time for run in seconds. */ +} CU_RunSummary; +typedef CU_RunSummary* CU_pRunSummary; /**< Pointer to CU_RunSummary. */ + +/*-------------------------------------------------------------------- + * Type Definitions for Message Handlers. + *--------------------------------------------------------------------*/ +typedef void (*CU_SuiteStartMessageHandler)(const CU_pSuite pSuite); +/**< Message handler called at the start of a suite. pSuite will not be null. */ + +typedef void (*CU_TestStartMessageHandler)(const CU_pTest pTest, const CU_pSuite pSuite); +/**< Message handler called at the start of a test. + * The parameters are the test and suite being run. The test run is + * considered in progress when the message handler is called. + * Neither pTest nor pSuite may be null. + */ + +typedef void (*CU_TestCompleteMessageHandler)(const CU_pTest pTest, const CU_pSuite pSuite, + const CU_pFailureRecord pFailure); +/**< Message handler called at the completion of a test. + * The parameters are the test and suite being run, plus a pointer to + * the first failure record applicable to this test. If the test did + * not have any assertion failures, pFailure will be NULL. The test run + * is considered in progress when the message handler is called. + */ + +typedef void (*CU_SuiteCompleteMessageHandler)(const CU_pSuite pSuite, + const CU_pFailureRecord pFailure); +/**< Message handler called at the completion of a suite. + * The parameters are suite being run, plus a pointer to the first failure + * record applicable to this suite. If the suite and it's tests did not + * have any failures, pFailure will be NULL. The test run is considered + * in progress when the message handler is called. + */ + +typedef void (*CU_AllTestsCompleteMessageHandler)(const CU_pFailureRecord pFailure); +/**< Message handler called at the completion of a test run. + * The parameter is a pointer to the linked list holding the failure + * records for the test run. The test run is considered completed + * when the message handler is called. + */ + +typedef void (*CU_SuiteInitFailureMessageHandler)(const CU_pSuite pSuite); +/**< Message handler called when a suite initializer fails. + * The test run is considered in progress when the message handler is called. + */ + +typedef void (*CU_SuiteCleanupFailureMessageHandler)(const CU_pSuite pSuite); +/**< Message handler called when a suite cleanup function fails. + * The test run is considered in progress when the message handler is called. + */ + +/*-------------------------------------------------------------------- + * Get/Set functions for Message Handlers + *--------------------------------------------------------------------*/ +CU_EXPORT void CU_set_suite_start_handler(CU_SuiteStartMessageHandler pSuiteStartMessage); +/**< Sets the message handler to call before each suite is run. */ +CU_EXPORT void CU_set_test_start_handler(CU_TestStartMessageHandler pTestStartMessage); +/**< Sets the message handler to call before each test is run. */ +CU_EXPORT void CU_set_test_complete_handler(CU_TestCompleteMessageHandler pTestCompleteMessage); +/**< Sets the message handler to call after each test is run. */ +CU_EXPORT void CU_set_suite_complete_handler(CU_SuiteCompleteMessageHandler pSuiteCompleteMessage); +/**< Sets the message handler to call after each suite is run. */ +CU_EXPORT void CU_set_all_test_complete_handler(CU_AllTestsCompleteMessageHandler pAllTestsCompleteMessage); +/**< Sets the message handler to call after all tests have been run. */ +CU_EXPORT void CU_set_suite_init_failure_handler(CU_SuiteInitFailureMessageHandler pSuiteInitFailureMessage); +/**< Sets the message handler to call when a suite initialization function returns an error. */ +CU_EXPORT void CU_set_suite_cleanup_failure_handler(CU_SuiteCleanupFailureMessageHandler pSuiteCleanupFailureMessage); +/**< Sets the message handler to call when a suite cleanup function returns an error. */ + +CU_EXPORT CU_SuiteStartMessageHandler CU_get_suite_start_handler(void); +/**< Retrieves the message handler called before each suite is run. */ +CU_EXPORT CU_TestStartMessageHandler CU_get_test_start_handler(void); +/**< Retrieves the message handler called before each test is run. */ +CU_EXPORT CU_TestCompleteMessageHandler CU_get_test_complete_handler(void); +/**< Retrieves the message handler called after each test is run. */ +CU_EXPORT CU_SuiteCompleteMessageHandler CU_get_suite_complete_handler(void); +/**< Retrieves the message handler called after each suite is run. */ +CU_EXPORT CU_AllTestsCompleteMessageHandler CU_get_all_test_complete_handler(void); +/**< Retrieves the message handler called after all tests are run. */ +CU_EXPORT CU_SuiteInitFailureMessageHandler CU_get_suite_init_failure_handler(void); +/**< Retrieves the message handler called when a suite initialization error occurs. */ +CU_EXPORT CU_SuiteCleanupFailureMessageHandler CU_get_suite_cleanup_failure_handler(void); +/**< Retrieves the message handler called when a suite cleanup error occurs. */ + +/*-------------------------------------------------------------------- + * Functions for running registered tests and suites. + *--------------------------------------------------------------------*/ +CU_EXPORT CU_ErrorCode CU_run_all_tests(void); +/**< + * Runs all tests in all suites registered in the test registry. + * The suites are run in the order registered in the test registry. + * For each suite, it is first checked to make sure it is active. + * Any initialization function is then called, the suite is run + * using run_single_suite(), and finally any suite cleanup function + * is called. If an error condition (other than CUE_NOREGISTRY) + * occurs during the run, the action depends on the current error + * action (see CU_set_error_action()). An inactive suite is not + * considered an error for this function. Note that the run + * statistics (counts of tests, successes, failures) are cleared + * each time this function is run, even if it is unsuccessful. + * + * @return A CU_ErrorCode indicating the first error condition + * encountered while running the tests. + * @see CU_run_suite() to run the tests in a specific suite. + * @see CU_run_test() for run a specific test only. + */ + +CU_EXPORT CU_ErrorCode CU_run_suite(CU_pSuite pSuite); +/**< + * Runs all tests in a specified suite. + * The suite need not be registered in the test registry to be + * run. It does, however, need to have its fActive flag set to + * CU_TRUE.

+ * + * Any initialization function for the suite is first called, + * then the suite is run using run_single_suite(), and any suite + * cleanup function is called. Note that the run statistics + * (counts of tests, successes, failures) are initialized each + * time this function is called even if it is unsuccessful. If + * an error condition occurs during the run, the action depends + * on the current error action (see CU_set_error_action()). + * + * @param pSuite The suite containing the test (non-NULL) + * @return A CU_ErrorCode indicating the first error condition + * encountered while running the suite. CU_run_suite() + * sets and returns CUE_NOSUITE if pSuite is NULL, or + * CUE_SUITE_INACTIVE if the requested suite is not + * activated. Other error codes can be set during suite + * initialization or cleanup or during test runs. + * @see CU_run_all_tests() to run all suites. + * @see CU_run_test() to run a single test in a specific suite. + */ + +CU_EXPORT CU_ErrorCode CU_run_test(CU_pSuite pSuite, CU_pTest pTest); +/**< + * Runs a specific test in a specified suite. + * The suite need not be registered in the test registry to be run, + * although the test must be registered in the specified suite. + * Any initialization function for the suite is first + * called, then the test is run using run_single_test(), and + * any suite cleanup function is called. Note that the + * run statistics (counts of tests, successes, failures) + * will be initialized each time this function is called even + * if it is not successful. Both the suite and test specified + * must be active for the test to be run. The suite is not + * considered to be run, although it may be counted as a failed + * suite if the intialization or cleanup functions fail. + * + * @param pSuite The suite containing the test (non-NULL) + * @param pTest The test to run (non-NULL) + * @return A CU_ErrorCode indicating the first error condition + * encountered while running the suite. CU_run_test() + * sets and returns CUE_NOSUITE if pSuite is NULL, + * CUE_NOTEST if pTest is NULL, CUE_SUITE_INACTIVE if + * pSuite is not active, CUE_TEST_NOT_IN_SUITE + * if pTest is not registered in pSuite, and CU_TEST_INACTIVE + * if pTest is not active. Other error codes can be set during + * suite initialization or cleanup or during the test run. + * @see CU_run_all_tests() to run all tests/suites. + * @see CU_run_suite() to run all tests in a specific suite. + */ + +/*-------------------------------------------------------------------- + * Functions for setting runtime behavior. + *--------------------------------------------------------------------*/ +CU_EXPORT void CU_set_fail_on_inactive(CU_BOOL new_inactive); +/**< + * Sets whether an inactive suite or test is treated as a failure. + * If CU_TRUE, then failure records will be generated for inactive + * suites or tests encountered during a test run. The default is + * CU_TRUE so that the client is reminded that the framewrork + * contains inactive suites/tests. Set to CU_FALSE to turn off + * this behavior. + * + * @param new_inactive New setting for whether to treat inactive + * suites and tests as failures during a test + * run (CU_TRUE) or not (CU_FALSE). + * @see CU_get_fail_on_failure() + */ + +CU_EXPORT CU_BOOL CU_get_fail_on_inactive(void); +/**< + * Retrieves the current setting for whether inactive suites/tests + * are treated as failures. If CU_TRUE then failure records will + * be generated for inactive suites encountered during a test run. + * + * @return CU_TRUE if inactive suites/tests are failures, CU_FALSE if not. + * @see CU_set_fail_on_inactive() + */ + +/*-------------------------------------------------------------------- + * Functions for getting information about the previous test run. + *--------------------------------------------------------------------*/ +CU_EXPORT unsigned int CU_get_number_of_suites_run(void); +/**< Retrieves the number of suites completed during the previous run (reset each run). */ +CU_EXPORT unsigned int CU_get_number_of_suites_failed(void); +/**< Retrieves the number of suites which failed to initialize during the previous run (reset each run). */ +CU_EXPORT unsigned int CU_get_number_of_suites_inactive(void); +/**< Retrieves the number of inactive suites found during the previous run (reset each run). */ +CU_EXPORT unsigned int CU_get_number_of_tests_run(void); +/**< Retrieves the number of tests completed during the previous run (reset each run). */ +CU_EXPORT unsigned int CU_get_number_of_tests_failed(void); +/**< Retrieves the number of tests containing failed assertions during the previous run (reset each run). */ +CU_EXPORT unsigned int CU_get_number_of_tests_inactive(void); +/**< Retrieves the number of inactive tests found during the previous run (reset each run). */ +CU_EXPORT unsigned int CU_get_number_of_asserts(void); +/**< Retrieves the number of assertions processed during the last run (reset each run). */ +CU_EXPORT unsigned int CU_get_number_of_successes(void); +/**< Retrieves the number of successful assertions during the last run (reset each run). */ +CU_EXPORT unsigned int CU_get_number_of_failures(void); +/**< Retrieves the number of failed assertions during the last run (reset each run). */ +CU_EXPORT unsigned int CU_get_number_of_failure_records(void); +/**< + * Retrieves the number failure records created during the previous run (reset each run). + * Note that this may be more than the number of failed assertions, since failure + * records may also be created for failed suite initialization and cleanup. + */ +CU_EXPORT double CU_get_elapsed_time(void); +/**< + * Retrieves the elapsed time for the last run in seconds (reset each run). + * This function will calculate the current elapsed time if the test run has not + * yet completed. This is in contrast to the run summary returned by + * CU_get_run_summary(), for which the elapsed time is not updated until the + * end of the run. + */ +CU_EXPORT CU_pFailureRecord CU_get_failure_list(void); +/**< + * Retrieves the head of the linked list of failures which occurred during the + * last run (reset each run). Note that the pointer returned is invalidated + * when the client initiates a run using CU_run_all_tests(), CU_run_suite(), + * or CU_run_test(). + */ +CU_EXPORT CU_pRunSummary CU_get_run_summary(void); +/**< + * Retrieves the entire run summary for the last test run (reset each run). + * The run counts and stats contained in the run summary are updated + * throughout a test run. Note, however, that the elapsed time is not + * updated until after all suites/tests are run but before the "all tests + * complete" message handler is called (if any). To get the elapsed + * time during a test run, use CU_get_elapsed_time() instead. + */ + +CU_EXPORT char * CU_get_run_results_string(void); +/**< + * Creates a string and fills it with a summary of the current run results. + * The run summary presents data for the suites, tests, and assertions + * encountered during the run, as well as the elapsed time. The data + * presented include the number of registered, run, passed, failed, and + * inactive entities for each, as well as the elapsed time. This function + * can be called at any time, although the test registry must have been + * initialized (checked by assertion). The returned string is owned by + * the caller and should be deallocated using CU_FREE(). NULL is returned + * if there is an error allocating the new string. + * + * @return A new string containing the run summary (owned by caller). + */ + +CU_EXPORT void CU_print_run_results(FILE *file); +/**< + * Prints a summary of the current run results to file. + * The run summary is the same as returned by CU_get_run_results_string(). + * Note that no newlines are printed before or after the report, so any + * positioning must be performed before/after calling this function. The + * report itself extends over several lines broken by '\n' characters. + * file may not be NULL (checked by assertion). + * + * @param file Pointer to stream to receive the printed summary (non-NULL). + */ + +/*-------------------------------------------------------------------- + * Functions for internal & testing use. + *--------------------------------------------------------------------*/ +CU_EXPORT CU_pSuite CU_get_current_suite(void); +/**< Retrieves a pointer to the currently-running suite (NULL if none). */ +CU_EXPORT CU_pTest CU_get_current_test(void); +/**< Retrievea a pointer to the currently-running test (NULL if none). */ +CU_EXPORT CU_BOOL CU_is_test_running(void); +/**< Returns CU_TRUE if a test run is in progress, + * CU_TRUE otherwise. + */ + +CU_EXPORT void CU_clear_previous_results(void); +/**< + * Initializes the run summary information stored from the previous test run. + * Resets the run counts to zero, and frees any memory associated with + * failure records. Calling this function multiple times, while inefficient, + * will not cause an error condition. + * @see clear_previous_results() + */ + +CU_EXPORT CU_BOOL CU_assertImplementation(CU_BOOL bValue, + unsigned int uiLine, + const char *strCondition, + const char *strFile, + const char *strFunction, + CU_BOOL bFatal); +/**< + * Assertion implementation function. + * All CUnit assertions reduce to a call to this function. It should only be + * called during an active test run (checked by assertion). This means that CUnit + * assertions should only be used in registered test functions during a test run. + * + * @param bValue Value of the assertion (CU_TRUE or CU_FALSE). + * @param uiLine Line number of failed test statement. + * @param strCondition String containing logical test that failed. + * @param strFile Source file where test statement failed. + * @param strFunction Function where test statement failed. + * @param bFatal CU_TRUE to abort test (via longjmp()), CU_FALSE to continue test. + * @return As a convenience, returns the value of the assertion (i.e. bValue). + */ + +#ifdef USE_DEPRECATED_CUNIT_NAMES +typedef CU_FailureRecord _TestResult; /**< @deprecated Use CU_FailureRecord. */ +typedef CU_pFailureRecord PTestResult; /**< @deprecated Use CU_pFailureRecord. */ +#endif /* USE_DEPRECATED_CUNIT_NAMES */ + +#ifdef CUNIT_BUILD_TESTS +void test_cunit_TestRun(void); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* CUNIT_TESTRUN_H_SEEN */ +/** @} */ diff --git a/pde-test-host/pde-test-host/include/Util.h b/pde-test-host/pde-test-host/include/Util.h new file mode 100755 index 0000000..c03085b --- /dev/null +++ b/pde-test-host/pde-test-host/include/Util.h @@ -0,0 +1,158 @@ +/* + * CUnit - A Unit testing framework library for C. + * Copyright (C) 2001 Anil Kumar + * Copyright (C) 2004-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 + */ + +/* + * Contains Type Definitions for some generic functions used across + * CUnit project files. + * + * 13/Oct/2001 Moved some of the generic functions declarations from + * other files to this one so as to use the functions + * consitently. This file is not included in the distribution + * headers because it is used internally by CUnit. (AK) + * + * 20-Jul-2004 New interface, support for deprecated version 1 names. (JDS) + * + * 5-Sep-2004 Added internal test interface. (JDS) + * + * 17-Apr-2006 Added CU_translated_strlen() and CU_number_width(). + * Removed CUNIT_MAX_STRING_LENGTH - dangerous since not enforced. + * Fixed off-by-1 error in CU_translate_special_characters(), + * modifying implementation & results in some cases. User can + * now tell if conversion failed. (JDS) + */ + +/** @file + * Utility functions (user interface). + */ +/** @addtogroup Framework + * @{ + */ + +#ifndef CUNIT_UTIL_H_SEEN +#define CUNIT_UTIL_H_SEEN + +#include "CUnit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CUNIT_MAX_ENTITY_LEN 5 +/**< Maximum number of characters in a translated xml entity. */ + +CU_EXPORT size_t CU_translate_special_characters(const char *szSrc, char *szDest, size_t maxlen); +/**< + * Converts special characters in szSrc to xml entity codes and stores + * result in szDest. Currently conversion of '&', '<', and '>' is supported. + * Note that conversion to entities increases the length of the converted + * string. The greatest conversion size increase would be a string + * consisting entirely of entity characters of converted length + * CUNIT_MAX_ENTITY_LEN. Neither szSrc nor szDest may be NULL + * (checked by assertion).

+ * + * maxlen gives the maximum number of characters in the translated string. + * If szDest does not have enough room to hold the converted string, the + * return value will be zero and szDest will contain an empty string. + * If this occurs, the remaining characters in szDest may be overwritten + * in an unspecified manner. It is the caller's responsibility to make + * sure there is sufficient room in szDest to hold the converted string. + * CU_translated_strlen() may be used to calculate the length of buffer + * required (remember to add 1 for the terminating \0). + * + * @param szSrc Source string to convert (non-NULL). + * @param szDest Location to hold the converted string (non-NULL). + * @param maxlen Maximum number of characters szDest can hold. + * @return The number of special characters converted (always 0 if + * szDest did not have enough room to hold converted string). + */ + +CU_EXPORT size_t CU_translated_strlen(const char *szSrc); +/**< + * Calculates the length of a translated string. + * This function calculates the buffer length required to hold a string + * after processing with CU_translate_special_characters(). The returned + * length does not include space for the terminating '\0' character. + * szSrc may not be NULL (checked by assertion). + * + * @param szSrc Source string to analyze (non-NULL). + * @return The number of characters szSrc will expand to when converted. + */ + +CU_EXPORT int CU_compare_strings(const char *szSrc, const char *szDest); +/**< + * Case-insensitive string comparison. Neither string pointer + * can be NULL (checked by assertion). + * + * @param szSrc 1st string to compare (non-NULL). + * @param szDest 2nd string to compare (non-NULL). + * @return 0 if the strings are equal, non-zero otherwise. + */ + +CU_EXPORT void CU_trim_left(char *szString); +/**< + * Trims leading whitespace from the specified string. + * @param szString The string to trim. + */ + +CU_EXPORT void CU_trim_right(char *szString); +/**< + * Trims trailing whitespace from the specified string. + * @param szString The string to trim. + */ + +CU_EXPORT void CU_trim(char *szString); +/**< + * Trims leading and trailing whitespace from the specified string. + * @param szString The string to trim. + */ + +CU_EXPORT size_t CU_number_width(int number); +/**< + * Calulates the number of places required to display + * number in decimal. + */ + +#ifdef CUNIT_BUILD_TESTS +void test_cunit_Util(void); +#endif + +#ifdef __cplusplus +} +#endif + +#ifdef USE_DEPRECATED_CUNIT_NAMES +#define CUNIT_MAX_STRING_LENGTH 1024 +/**< Maximum string length. */ +#define translate_special_characters(src, dest, len) CU_translate_special_characters(src, dest, len) +/**< Deprecated (version 1). @deprecated Use CU_translate_special_characters(). */ +#define compare_strings(src, dest) CU_compare_strings(src, dest) +/**< Deprecated (version 1). @deprecated Use CU_compare_strings(). */ + +#define trim_left(str) CU_trim_left(str) +/**< Deprecated (version 1). @deprecated Use CU_trim_left(). */ +#define trim_right(str) CU_trim_right(str) +/**< Deprecated (version 1). @deprecated Use CU_trim_right(). */ +#define trim(str) CU_trim(str) +/**< Deprecated (version 1). @deprecated Use CU_trim(). */ + +#endif /* USE_DEPRECATED_CUNIT_NAMES */ + +#endif /* CUNIT_UTIL_H_SEEN */ +/** @} */ diff --git a/pde-test-host/pde-test-host/include/assert.h b/pde-test-host/pde-test-host/include/assert.h new file mode 100644 index 0000000..6f784d3 --- /dev/null +++ b/pde-test-host/pde-test-host/include/assert.h @@ -0,0 +1,44 @@ +/* + * $Id: assert.h,v 1.1 Broadcom SDK $ + * $Copyright: (c) 2018 Broadcom. + * Broadcom Proprietary and Confidential. All rights reserved.$ + * + * This version of assert.h should appear in the compiler include path + * ahead of any other version of assert.h to ensure that _sal_assert is + * used for all assertion failures. + */ + +#ifndef _ASSERT_H +#define _ASSERT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__STDC__) || defined(__BORLAND__) +extern void _sal_assert(const char *, const char *, int); +#else +extern void _sal_assert(); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _ASSERT_H */ + +#undef assert + +#ifdef NDEBUG + +#define assert(EX) ((void)0) + +#else + +#if defined(__STDC__) +#define assert(EX) (void)((EX) || (_sal_assert(#EX, __FILE__, __LINE__), 0)) +#else +#define assert(EX) (void)((EX) || (_sal_assert("EX", __FILE__, __LINE__), 0)) +#endif /* __STDC__ */ + +#endif /* NDEBUG */ diff --git a/pde-test-host/pde-test-host/include/brcm_avl.h b/pde-test-host/pde-test-host/include/brcm_avl.h new file mode 100755 index 0000000..9e9d6df --- /dev/null +++ b/pde-test-host/pde-test-host/include/brcm_avl.h @@ -0,0 +1,52 @@ +/********************************************************************* + * + * Copyright: (c) 2017 Broadcom. + * Broadcom Proprietary and Confidential. All rights reserved. + * + *********************************************************************/ + +#ifndef _AVL_H_ +#define _AVL_H_ + + +#define AVL_LESS_THAN -1 +#define AVL_EQUAL 0 +#define AVL_GREATER_THAN 1 + + +#if defined(FUTURE_RELEASE) && FUTURE_RELEASE +/* defines for type of avl tree*/ + #define MAC_ADDR 1 + #define QVLAN_ADDR 2 + #define MAC_FILTER 3 +/* -----------------------------*/ +#endif + +#ifndef _AVL_MAX_DEPTH +#define _AVL_MAX_DEPTH 32 +#endif + +#define _LEFT 0 +#define _RIGHT 1 +#define _LEFT_WEIGHT -1 +#define _RIGHT_WEIGHT 1 + +void* avlNewNewDataNode(avlTree_t *avl_tree ); +void avlNewFreeDataNode(avlTree_t * avl_tree, void *ptr); +void * avlRemoveEntry( avlTree_t *avl_tree, void *item); +void ** avlFindEntry(avlTree_t *avl_tree, void *item); +void * avlAddEntry( avlTree_t *avl_tree, void *item); +int avlCompareKey(void *item, + void *DataItem, + unsigned int lengthSearchKey, + avlComparator_t func); +void swapNodes (int direction, avlTreeTables_t *oldUpper, + avlTreeTables_t *oldLower); +avlTreeTables_t *rotateNodes (int otherDirection, avlTreeTables_t *node1, + avlTreeTables_t *node2); +void balance (avlTreeTables_t *q, avlTreeTables_t *s, + avlTreeTables_t *t, avlTree_t *avl_tree, int direction); +avlTreeTables_t *removeAndBalance (avlTreeTables_t *s, int direction, + unsigned int *done); + +#endif diff --git a/pde-test-host/pde-test-host/include/brcm_avl_api.h b/pde-test-host/pde-test-host/include/brcm_avl_api.h new file mode 100755 index 0000000..3d7dd7a --- /dev/null +++ b/pde-test-host/pde-test-host/include/brcm_avl_api.h @@ -0,0 +1,414 @@ +/********************************************************************* + * + * Copyright: (c) 2017 Broadcom. + * Broadcom Proprietary and Confidential. All rights reserved. + * + *********************************************************************/ + +#ifndef _AVL_API_H_ +#define _AVL_API_H_ + +#include + +/********************************************************************* +* +* @structures avlTreeTables_s +* +* @purpose this is the generic tree table structure. +* all data structures need to have this defined +* +* @notes this stores all the information needed for the +* traversal of the tree with poiters to +* the data item and links to its subtrees +* +*********************************************************************/ +typedef struct avlTreeTables_s +{ + signed char balance; /* Balance factor. */ + char balanceNeeded; /* Used during insertion. */ + struct avlTreeTables_s *link[2]; /* Subtrees. */ + void *data; /* Pointer to data. */ +} avlTreeTables_t; + +/* + * @purpose Function pointer type for AVL tree comparators + * + * @notes This is the prototype that a custom AVL tree comparator + * must match. The arguments 'a' and 'b' are pointers to + * space containing a key of the type used by the particular + * tree in question. The 'l' argument is a length specifier + * which may or may not be used by the comparator (most + * custom comparators will know the length of the keys to + * be compared, but some may not). + * + * The comparator function must accept these arguments, and + * return a determination of 'a' greater than 'b', 'a' + * less than 'b', or 'a' equal to 'b', using locally defined + * rules for greater than, less than, and equal to. The only + * constraints on those rules are that greater than and less + * than must return a consistent result when given the same + * pair of keys in the same order, and equal to must uniquely + * identify a key in the domain of all possible keys in the + * tree. + * + * NOTE: The use of 'size_t' in this context is specifically + * sanctioned by the CRC since this prototype must + * match the memcmp(3) prototype, and the size_t + * usage here is not problematic. Because the size + * of a size_t varies widely, there are cases + * in which the use of size_t can cause portability + * concerns. In particular, those concerns arize over + * bitwise operations or operations that are aware of + * the maximum value that a size_t can represent. + * Neither of these concerns apply here. + * + * This declaration should not be seen as precedent + * for general use of size_t parameters. + */ +typedef int (*avlComparator_t)(const void *a, const void *b, size_t l); + +/********************************************************************* +* +* @structures avl_tree_s +* +* @purpose this is the generic avl tree structure +* +* @notes contains all the information needed for the working +* of the avl tree +* +*********************************************************************/ +typedef struct avl_tree_s +{ + unsigned int type; /* type of data to be stored */ + unsigned int lengthData; /* length of data */ + void *semId; /* semaphore id for this avl tree */ + unsigned int offset_next; /* offset to the 'next' member of the data structure*/ + unsigned int lengthSearchKey; /* length of the serch key of the data structure*/ + avlTreeTables_t *currentTableHeap; /* pointer to the current position of the table heap*/ + avlTreeTables_t *initialTableHeap; /* pointer to the first position of the table heap*/ + void *currentDataHeap; /* pointer to the current position of the data heap*/ + void *initialDataHeap; /* pointer to the first position of the data heap*/ + avlTreeTables_t root; /* Tree root node. */ + unsigned int count; /* Number of nodes in the tree. */ + void *value; /* Arbitary user data. */ + avlComparator_t compare; /* Comparator func ptr (default: memcmp()) */ + + /* The following pointers are only set if the memory was allocated */ + /* by avlAllocAndCreateAvlTree and must be freed by avlDeleteAvlTree */ + unsigned int componentId; + avlTreeTables_t *tableHeap; /* pointer to the table heap */ + void *dataHeap; /* pointer to the data heap*/ +} avlTree_t; + + + +#define AVL_EXACT 1 +#define AVL_NEXT 2 + +/********************************************************************* +* @purpose Creates the generic avl tree structure and initialize +* +* @param tree pointer to the tree structure +* @param treeHeap pointer to the tree heap +* @param dataHeap pointer to the data heap +* @param max_entries maximum number of entries in the tree +* @param dataLength length of a data entry +* @param type type of data +* @param lengthSearchKey length of the search key +* +* @returns AvlTree_t pointer to the generic avl tree structure if successful +* @returns 0 if not successful +* +* @notes RESTRICTIONS:1. the first field in the data structure (of the +* data heap) must be the key +* 2. the last field in the data structure (of the data +* heap) must be a void pointer type +* +* +* @end +*********************************************************************/ +void avlCreateAvlTree(avlTree_t *tree, avlTreeTables_t *treeHeap, void *dataHeap, + unsigned int max_entries, unsigned int dataLength, unsigned int type, + unsigned int lengthSearchKey); + +/********************************************************************* +* @purpose Creates the generic avl tree structure and initialize +* +* @param tree pointer to the tree structure +* @param treeHeap pointer to the tree heap +* @param dataHeap pointer to the data heap +* @param max_entries maximum number of entries in the tree +* @param dataLength length of a data entry +* @param type type of data +* @param lengthSearchKey length of the search key +* +* @returns AvlTree_t pointer to the generic avl tree structure if successful +* @returns 0 if not successful +* +* @notes RESTRICTIONS:1. the first field in the data structure (of the +* data heap) must be the key +* 2. the last field in the data structure (of the data +* heap) must be a void pointer type +* +* +* @end +*********************************************************************/ +void avlCreateAvlTreeProcLib(avlTree_t *tree, avlTreeTables_t *treeHeap, void *dataHeap, + unsigned int max_entries, unsigned int dataLength, unsigned int type, + unsigned int lengthSearchKey); + +/********************************************************************* +* @purpose Set the comparator function for an AVL tree +* +* @param tree pointer to the tree structure +* @param compare pointer to the new comparator function +* if NULL is used, the default comparator +* (memcmp()) will be used. +* +* @returns pointer to the previous comparator (this function does not fail) +* +* @notes The default comparator in a generic avl tree is memcmp() +* There are also some canned comparators supplied (these are +* declared below). If the user wants to provide a new type +* specific comparator it should have the same signature as +* memcmp(): +* +* int bar(void *a, void *b, size_t key_len); +* +* and it should have the following integer return values: +* +* >0 (I generally use 1) if a > b +* 0 if a == b +* <0 if a < b +* +* The algorithm for the comparison and the definitions +* of <, >, and == belong entirely to the comparator. The +* only requirements are that < and > are consistent, and +* == ensures uniqueness within the tree. +* @end +*********************************************************************/ +avlComparator_t avlSetAvlTreeComparator(avlTree_t *t, avlComparator_t c); + +/********************************************************************* +* @purpose Deletes an avl tree structure +* +* @param tree pointer to an avl tree structure +* +* @returns 0 +* @returns -1 +* @returns -2 +* +* @notes +* +* @end +*********************************************************************/ +int avlDeleteAvlTreeProcLib(avlTree_t *tree); + +/********************************************************************* +* @purpose Resets all entries but the root node +* +* @param avl_tree pointer to the avl tree structure +* @param max_entries max number of entries in the structure +* +* @returns void +* +* @notes +* +* @end +*********************************************************************/ +void avlPurgeAvlTree (avlTree_t *avl_tree, unsigned int max_entries); +/********************************************************************* +* @purpose Inserts ITEM into TREE. Returns NULL if the item was inserted, +* otherwise a pointer to the duplicate item +* +* @param avl_tree pointer to the avl tree structure +* @param item pointer to item to be inserted +* +* @returns 0 if item was inserted +* @returns void pointer to a duplicate item, if duplicate exists +* @returns void pointer to item, if error +* +* @notes +* +* @end +*********************************************************************/ +void * avlInsertEntry( avlTree_t *avl_tree, void *item); +/********************************************************************* +* @purpose Searches AVL tree for an item matching ITEM. If found, the +* item is removed from the tree and the actual item found is returned +* to the caller. If no item matching ITEM exists in the tree, +* returns NULL. +* +* @param avl_tree pointer to the avl tree structure +* @param item pointer to item to be deleted +* +* @returns void * pointer to the item if deleted +* @returns 0 if item does not exist in the tree +* +* @notes +* +* @end +*********************************************************************/ +void * avlDeleteEntry (avlTree_t *avl_tree, void *item); +/***************************************************************** +* @purpose Searches AVL tree for exact or get next match +* +* @param avl_tree pointer to the avl tree structure +* @param item pointer to item to be found +* @param matchType AVL_EXACT or AVL_NEXT +* +* @returns void * pointer to the item if matched +* @returns 0 if item does not exist in the tree +* +* @notes +* +* @end +*****************************************************************/ +void * avlSearch (avlTree_t *avl_tree, void *key, unsigned int flags); + +/***************************************************************** +* @purpose Obtains count of nodes in the tree +* +* @param avl_tree pointer to the avl tree structure +* +* @returns count count of items in the tree +* +* @notes +* +* @end +*****************************************************************/ +unsigned int avlTreeCount (avlTree_t *avl_tree); + +/***************************************************************** +* @purpose Compare short (16 bit signed keys) and indicate relationship +* +* @param a Pointer to the first key +* @param b Pointer to the second key +* @param len Length of the key (unused) +* +* @returns 0 if the keys are equal +* @returns 1 if key 'a' is greater than key 'b' +* @returns -1 if key 'a' is less than key 'b' +* +* @notes +* +* @end +*****************************************************************/ +int avlCompareShort16(const void *a, const void *b, size_t len); + +/***************************************************************** +* @purpose Compare long (32 bit signed keys) and indicate relationship +* +* @param a Pointer to the first key +* @param b Pointer to the second key +* @param len Length of the key (unused) +* +* @returns 0 if the keys are equal +* @returns 1 if key 'a' is greater than key 'b' +* @returns -1 if key 'a' is less than key 'b' +* +* @notes +* +* @end +*****************************************************************/ +int avlCompareLong32(const void *a, const void *b, size_t len); + +/***************************************************************** +* @purpose Compare ushort (16 bit unsigned keys) and indicate relationship +* +* @param a Pointer to the first key +* @param b Pointer to the second key +* @param len Length of the key (unused) +* +* @returns 0 if the keys are equal +* @returns 1 if key 'a' is greater than key 'b' +* @returns -1 if key 'a' is less than key 'b' +* +* @notes +* +* @end +*****************************************************************/ +int avlCompareUShort16(const void *a, const void *b, size_t len); + +/***************************************************************** +* @purpose Compare ulong (32 bit unsigned keys) and indicate relationship +* +* @param a Pointer to the first key +* @param b Pointer to the second key +* @param len Length of the key (unused) +* +* @returns 0 if the keys are equal +* @returns 1 if key 'a' is greater than key 'b' +* @returns -1 if key 'a' is less than key 'b' +* +* @notes +* +* @end +*****************************************************************/ +int avlCompareULong32(const void *a, const void *b, size_t len); + +/***************************************************************** +* @purpose Compare IP Address keys and indicate relationship +* +* @param a Pointer to the first key +* @param b Pointer to the second key +* @param len Length of the key (unused) +* +* @returns 0 if the keys are equal +* @returns 1 if key 'a' is greater than key 'b' +* @returns -1 if key 'a' is less than key 'b' +* +* @notes +* +* @end +*****************************************************************/ +int avlCompareIPAddr(const void *a, const void *b, size_t len); + +/***************************************************************** +* @purpose Compare IP Network Address (Address and Mask) keys and +* indicate relationship +* +* @param a Pointer to the first key +* @param b Pointer to the second key +* @param len Length of the key (unused) +* +* @returns 0 if the keys are equal +* @returns 1 if key 'a' is greater than key 'b' +* @returns -1 if key 'a' is less than key 'b' +* +* @notes +* +* @end +*****************************************************************/ +int avlCompareIPNetAddr(const void *a, const void *b, size_t len); + +/********************************************************************* +* @purpose Creates the generic avl tree structure and initialize +* +* @param avlTree pointer to the tree structure +* @param max_entries maximum number of entries in the tree +* @param dataLength length of a data entry +* @param type type of data +* @param compareFcn pointer to the comparator function +* if NULL is used, the default comparator +* (memcmp()) will be used. +* @param lengthSearchKey length of the search key +* +* @returns 0 if avl tree initialization was successful +* @returns -1 if not successful +* +* @notes RESTRICTIONS:1. First field in the data structure +* (of data heap) must be the key +* 2. Last field in the data structure +* (of data heap) must be a void pointer type +* +* @end +*********************************************************************/ +int avlAllocAndCreateAvlTreeProcLib(avlTree_t *avlTree, + unsigned int max_entries, + unsigned int dataLength, + unsigned int type, + avlComparator_t compareFcn, + unsigned int lengthSearchKey); + +#endif diff --git a/pde-test-host/pde-test-host/include/brcm_sai_common.h b/pde-test-host/pde-test-host/include/brcm_sai_common.h new file mode 100755 index 0000000..e63992b --- /dev/null +++ b/pde-test-host/pde-test-host/include/brcm_sai_common.h @@ -0,0 +1,199 @@ +/********************************************************************* + * + * Copyright: (c) 2017 Broadcom. + * Broadcom Proprietary and Confidential. All rights reserved. + * + *********************************************************************/ + +#if !defined (_BRM_SAI_COMMON) +#define _BRM_SAI_COMMON + +/* +################################################################################ +# Public includes # +################################################################################ +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +################################################################################ +# All internal includes # +################################################################################ +*/ +#include "types.h" + +#include "brcm_sai_version.h" +#include "brcm_syncdb.h" +#include "driver_util.h" + +#ifdef PRINT_TO_SYSLOG +#include +#endif + +/* +################################################################################ +# Common defines # +################################################################################ +*/ +#ifndef STATIC +#define STATIC +#endif /* !STATIC */ + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef INGRESS +#define INGRESS 0 +#endif +#ifndef EGRESS +#define EGRESS 1 +#endif +#ifndef MATCH +#define MATCH 0 +#endif + +#define COLD_BOOT 0 +#define WARM_BOOT 1 +#define FAST_BOOT 2 + +#define _BRCM_SAI_MASK_8 0xFF +#define _BRCM_SAI_MASK_16 0xFFFF +#define _BRCM_SAI_MASK_32 0xFFFFFFFF +#define _BRCM_SAI_MASK_64 0xFFFFFFFFFFFFFFFF +#define _BRCM_SAI_MASK_64_UPPER_32 0xFFFFFFFF00000000 +#define _BRCM_SAI_MASK_64_LOWER_32 0x00000000FFFFFFFF +#define _BCAST_MAC_ADDR { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } +#define _BCM_L3_HOST_AS_ROUTE 0 + + + +/* +################################################################################ +# Platform based defines # +################################################################################ +*/ +#define _CPU_L0_NODES 1 +#define _L0_NODES 2 + +#define NUM_CPU_L1_NODES 2 + +/* This is the max so far - seen in TH3 */ +#define NUM_QUEUES 12 +#define NUM_L1_NODES 10 +#define NUM_L2_NODES 2 + +#define NUM_TH_QUEUES 10 +#define NUM_TH_CPU_L0_NODES 10 +#define NUM_TH_CPU_MC_QUEUES 48 +#define NUM_TH_L0_NODES 10 + +#define NUM_TH3_CPU_L1_NODES 2 +#define NUM_TH3_CPU_L0_NODES 12 +#define NUM_TH3_CPU_MC_QUEUES 48 +#define NUM_TH3_L0_NODES 12 +#define NUM_TH3_L1_NODES 2 + + +#define NUM_TD2_CPU_QUEUES 8 +#define NUM_TD2_CPU_L0_NODES 1 +#define NUM_TD2_CPU_MC_QUEUES 16 /* h/w supports 48 but limiting based on expected usage */ +#define NUM_TD2_L0_NODES 2 +#define NUM_TD2_L1_PER_L0 8 +#define NUM_TD2_L2_NODES 2 + +#define NUM_HX4_QUEUES 8 +#define NUM_HX4_L1_NODES 8 +#define NUM_HX4_CPU_QUEUES 8 +#define NUM_HX4_CPU_L0_NODES 1 +#define NUM_HX4_CPU_MC_QUEUES 16 /* h/w supports 48 but limiting based on expected usage */ +#define NUM_HX4_L0_NODES 1 +#define NUM_HX4_L1_PER_L0 8 + +#define NUM_TH3_PFC_PRIORITIES SOC_MMU_CFG_PRI_GROUP_MAX + +#define TOTAL_SCHED_NODES_PER_PORT 13 /* This is the current max but will change based on device type */ + +#define _BRCM_SAI_MAX_HIERARCHY_TD2 3 +#define _BRCM_SAI_MAX_HIERARCHY_TH 2 + +#ifndef MAX +#define MAX(a, b) (a > b ? a : b) +#endif +#define NUM_L0_NODES MAX(NUM_TH3_CPU_L0_NODES, NUM_TD2_CPU_L0_NODES) +#define NUM_CPU_MC_QUEUES MAX(NUM_TH_CPU_MC_QUEUES, NUM_TD2_CPU_MC_QUEUES) + +#define _BRCM_SAI_MAX_ECMP_MEMBERS 16384 +#define _BRCM_HX4_MAX_ECMP_MEMBERS 4096 +#define _BRCM_HX4_MAX_FDB_ENTRIES 32768 +#define _BRCM_TD3_MAX_ECMP_MEMBERS 32768 + +/* Note: This is chip specific - best to have a SDK/SOC api to retreive this from */ +#define TOTAL_TD2_MMU_BUFFER_SIZE (59941*208/1000) /* In KB */ +#define TOTAL_TH_MMU_BUFFER_SIZE (16*1024*1024) /* In KB */ + + +#if defined(BCM_TRIDENT3_SUPPORT) +#define TOTAL_TD3_MMU_BUFFER_SIZE (_TD3_MMU_TOTAL_CELLS * 256 / 1000 ) /* In KB */ +#else +#define TOTAL_TD3_MMU_BUFFER_SIZE 0 +#endif + +#if defined(BCM_TOMAHAWK2_SUPPORT) +#define TOTAL_TH2_MMU_BUFFER_SIZE (_TH2_MMU_TOTAL_CELLS * 208 / 1000 ) /* In KB */ +#else +#define TOTAL_TH2_MMU_BUFFER_SIZE 0 +#endif + +#if defined(BCM_TOMAHAWK3_SUPPORT) +#define TOTAL_TH3_MMU_BUFFER_SIZE (_TH3_MMU_TOTAL_CELLS_PER_ITM * 2 * 254 / 1000 ) /* In KB */ +#define _BRCM_TH3_IFP_TCAM_SMALL_SLICE_SIZE 256 +#else +#define TOTAL_TH3_MMU_BUFFER_SIZE 0 +#define _BRCM_TH3_IFP_TCAM_SMALL_SLICE_SIZE 0 +#endif + +/* +################################################################################ +# Common internal defines # +################################################################################ +*/ +#define BRCM_SAI_API_ID_MIN SAI_API_UNSPECIFIED+1 +#define BRCM_SAI_API_ID_MAX SAI_API_BRIDGE /* FIXME: Check and Update */ + +#define _BRCM_SAI_CMD_BUFF_SIZE 512 +#define _BRCM_SAI_FILE_PATH_BUFF_SIZE 256 + +#define _BRCM_SAI_VR_MAX_VID 4094 +#define _BRCM_SAI_VR_DEFAULT_TTL 0 /* This is the MCAST ttl threshold */ +#define _BRCM_SAI_MAX_PORTS 220 /* Max logical port number used by underlying SDK/driver (TH) */ +#define _BRCM_SAI_MAX_HOSTIF 128 +#define _BRCM_SAI_MAX_FILTERS_PER_INTF 32 +#define _BRCM_SAI_MAX_TUNNELS (1024+1) +#define _BRCM_SAI_MAX_TUNNEL_RIFS (_BRCM_SAI_MAX_TUNNELS*2) +#define _BRCM_SAI_MAX_UDF_GROUPS 64 +#define _BRCM_SAI_MAX_HASH 32 +#define _BRCM_SAI_MAX_TRAP_GROUPS 64 +#define _BRCM_SAI_MAX_TRAPS 128 +#define _BRCM_SAI_MAX_HOSTIF_TABLE_ENTRIES 128 + + +#define BRCM_SAI_GET_OBJ_VAL(type, var) ((type)var) + + + +#endif /* _BRM_SAI_COMMON */ diff --git a/pde-test-host/pde-test-host/include/brcm_sai_extensions.h b/pde-test-host/pde-test-host/include/brcm_sai_extensions.h new file mode 100644 index 0000000..3ab4644 --- /dev/null +++ b/pde-test-host/pde-test-host/include/brcm_sai_extensions.h @@ -0,0 +1,54 @@ +/********************************************************************* + * + * Copyright: (c) 2017 Broadcom. + * Broadcom Proprietary and Confidential. All rights reserved. + * + *********************************************************************/ + +#if !defined (__SAI_H_) +#include +#endif + +#if !defined (_BRM_SAI_EXT) +#define _BRM_SAI_EXT + +/** Switch module extentions **/ + +/* Get sdk boot time in sec */ +#define SAI_SWITCH_ATTR_GET_SDK_BOOT_TIME SAI_SWITCH_ATTR_CUSTOM_RANGE_START +/* + * Register callback fn for getting sdk shutdown time in sec. + * This will be invoked just before switch_remove exits. + */ +#define SAI_SWITCH_ATTR_SDK_SHUT_TIME_GET_FN SAI_SWITCH_ATTR_CUSTOM_RANGE_START+1 +typedef void (*brcm_sai_sdk_shutdown_time_cb_fn)(int unit, unsigned int time_sec); + +/** ACL module extentions **/ + +#define SAI_ACL_TABLE_ATTR_FIELD_BTH_OPCODE SAI_ACL_TABLE_ATTR_CUSTOM_RANGE_START +#define SAI_ACL_TABLE_ATTR_FIELD_AETH_SYNDROME SAI_ACL_TABLE_ATTR_CUSTOM_RANGE_START + 1 +/* Set to true by default; set this to false in order to exclude inPorts from a field group's QSET */ +#define SAI_ACL_TABLE_ATTR_QUALIFIER_INPORTS SAI_ACL_TABLE_ATTR_CUSTOM_RANGE_START + 2 + +#define SAI_ACL_ENTRY_ATTR_FIELD_BTH_OPCODE SAI_ACL_ENTRY_ATTR_CUSTOM_RANGE_START +#define SAI_ACL_ENTRY_ATTR_FIELD_AETH_SYNDROME SAI_ACL_ENTRY_ATTR_CUSTOM_RANGE_START+1 + +/* BRCM specific custom attribute for pool id */ +#define BRCM_SAI_BUFFER_POOL_CUSTOM_START +#define SAI_BUFFER_POOL_ATTR_BRCM_CUSTOM_POOL_ID (SAI_BUFFER_POOL_ATTR_CUSTOM_RANGE_START) + +/* BRCM specific custom attribute for xpe-wide pool stats */ +#define SAI_BUFFER_POOL_STAT_CUSTOM_XPE0 (SAI_BUFFER_POOL_STAT_CUSTOM_RANGE_BASE | 1 << 10) +#define SAI_BUFFER_POOL_STAT_CUSTOM_XPE1 (SAI_BUFFER_POOL_STAT_CUSTOM_RANGE_BASE | 2 << 10) + +#define SAI_BUFFER_POOL_STAT_CURR_OCCUPANCY_BYTES_XPE0 \ + (SAI_BUFFER_POOL_STAT_CURR_OCCUPANCY_BYTES | SAI_BUFFER_POOL_STAT_CUSTOM_XPE0) + +#define SAI_BUFFER_POOL_STAT_CURR_OCCUPANCY_BYTES_XPE1 \ + (SAI_BUFFER_POOL_STAT_CURR_OCCUPANCY_BYTES | SAI_BUFFER_POOL_STAT_CUSTOM_XPE1) + + +/* BRCM specific custom attribute for profile */ +#define SAI_BUFFER_PROFILE_ATTR_BRCM_CUSTOM_USE_QGROUP_MIN (SAI_BUFFER_PROFILE_ATTR_CUSTOM_RANGE_START) + +#endif /* _BRM_SAI_EXT */ diff --git a/pde-test-host/pde-test-host/include/brcm_sai_version.h b/pde-test-host/pde-test-host/include/brcm_sai_version.h new file mode 100755 index 0000000..39dd163 --- /dev/null +++ b/pde-test-host/pde-test-host/include/brcm_sai_version.h @@ -0,0 +1,21 @@ +/********************************************************************* + * + * Copyright: (c) 2017 Broadcom. + * Broadcom Proprietary and Confidential. All rights reserved. + * + *********************************************************************/ + +#define BRCM_SAI_VER "3.4.4.7" +#define OCP_SAI_VER "1.3.6" +#define SDK_VER "6.5.14" +#define CANCUN_VER "5.1.8" + +typedef struct _brcm_sai_version_s { + char *brcm_sai_ver; + char *ocp_sai_ver; + char *sdk_ver; + char *cancun_ver; +} _brcm_sai_version_t; + +_brcm_sai_version_t brcm_sai_version_get(); + diff --git a/pde-test-host/pde-test-host/include/brcm_syncdb.h b/pde-test-host/pde-test-host/include/brcm_syncdb.h new file mode 100755 index 0000000..0e93389 --- /dev/null +++ b/pde-test-host/pde-test-host/include/brcm_syncdb.h @@ -0,0 +1,469 @@ +/********************************************************************* + * + * Copyright: (c) 2017 Broadcom. + * Broadcom Proprietary and Confidential. All rights reserved. + * + *********************************************************************/ + +#ifndef SYNCDB_H_INCLUDED +#define SYNCDB_H_INCLUDED + +#include +#include + +#include + +/* NVRAM archive file name. +** All syncdb tables enabled for NVRAM archiving are combined into this archive. +*/ +#define SYNCDB_NVRAM_ARCHIVE "/brcm_sai_syncdb.dat" + +/* Maximum number of clients that can use the database. +** The value must be divisible by 8. +** The value affects the bit mask size in each AVL table node. +*/ +#define CLIENT_MAX_LIMIT (8 * 64) + +/* Maximum client ID. +** This value must be the same or greater than CLIENT_MAX_LIMIT +** and evenly divisible by the CLIENT_MAX_LIMIT. +*/ +#define CLIENT_MAX_ID ((65536 / CLIENT_MAX_LIMIT) * CLIENT_MAX_LIMIT) + +/* Bit mask size containing a bit for each client. +*/ +#define CLIENT_MASK_SIZE (CLIENT_MAX_LIMIT / 8) + +/* Set a bit corresponding to the client ID in the client mask. +*/ +#define CLIENT_MASK_SET(client,mask) \ + (((unsigned char *)(mask))[(client)/8] |= 1 << ((client) - 8*((client)/8))) + +/* Clear a bit corresponding to the client ID in the client mask. +*/ +#define CLIENT_MASK_CLEAR(client,mask) \ + (((unsigned char *)(mask))[(client)/8] &= ~(1 << ((client) - 8*((client)/8)))) + +/* Check whether specified client bit is set in the mask. +** Return 0 if not set and non-zero if set. +*/ +#define CLIENT_MASK_IS_SET(client,mask) \ + ((((unsigned char *)(mask))[(client)/8]) & (1 << ((client) - 8*((client)/8)))) + +/* Hash table size of the data table names. +** This value must be a power of 2 and less or equal to (1 << 16). +*/ +#define TABLE_NAME_HASH_SIZE (1 << 13) + + +/* Client Table Node. +*/ +typedef struct +{ + unsigned int client_id; /* Unique Client ID in the range from 0 to (CLIENT_MAX_LIMIT-1) */ + pid_t client_pid; /* Client Process ID */ + struct sockaddr_un client_socket_name; /* UNIX Domain Socket Name for the Client */ + struct sockaddr_un client_notify_socket_name; /* UNIX Domain Socket Name for the Client table changes */ + int reply_socket_id; /* Client Command Reply Socket ID */ + int event_socket_id; /* Client Event Notification Socket ID */ + unsigned char client_description[SYNCDB_MAX_STR_LEN]; /* User-Provided Client Description */ + + /******************************************************** + ** The following information is used only for debugging. + ********************************************************/ + unsigned long long num_commands; /* Total number of commands issued by this client */ + + /* Number of table change events sent by the syncdb process to this client. + */ + unsigned long long num_table_change_events; + + /* If a client is registered for AVL Table events, and an AVL table entry + ** is deleted from the table before the client has the chance to process + ** the delete notification, then syncdb sends an event to the client indicating + ** that the table has been purged and that full table resyncrhonization + ** is required for this client. The counter keeps track of how many such table purges + ** happened for this client. + */ + unsigned long long num_table_purges; + +} clientTableNode_t; + +/* Do not change the table order. +*/ +typedef enum { + TABLE_TYPE_RECORD = 0, + TABLE_TYPE_AVL, + TABLE_TYPE_LAST /* Must be the last field in the table */ +} tableType_e; + +/* Data Table Node. +*/ +typedef struct dataTableNode_s +{ + char table_name [SYNCDB_TABLE_NAME_SIZE]; + unsigned char table_version; + + /* Flags passed on the create call. + */ + unsigned int create_flags; + + tableType_e table_type; /* Record, Storable-Record, AVL Tree */ + + /* The size of each record. This value must be less or + ** equal to SYNCDB_RECORD_MAX_SIZE. + */ + int record_size; + + /* Number of records currently in the table. + ** Always 1 for Record and Storable-Record. + ** 0 to max_records for AVL trees. + */ + int num_records; + + /* Number of records that are not pending for deletion. + ** Valid only for AVL trees. + */ + int num_non_deleted_records; + + /* Maximum number of records in the table. + ** Always 1 for Record and Storable-Record. + */ + int max_records; + + /* This attribute is applicable only to AVL trees. + ** The attribute specifies the maximum number of entries in the table that + ** are not pending for deletion. + */ + int max_non_deleted_records; + + /* Pointer to the data record. + */ + void *record_ptr; + + /* Pointer for linking the nodes inside the hash lookup table. + */ + struct dataTableNode_s *next_hash; + + /* Clients registered for notifications when changes are made to + ** this table. The clients are represented as a bit mask indexed + ** by the client ID. + */ + unsigned char notify_clients_mask [CLIENT_MASK_SIZE]; + + /* Per-Client mask indicating that this table has been created. + ** The first access to syncdbTableStatusGet() clears the flag. + */ + unsigned char table_created_client_mask [CLIENT_MASK_SIZE]; + + /* Per client mask indicating that something changed in the table. + ** The flag is set on Insert/Delete/Set command and cleared + ** on syncdbTableStatusGet(). + */ + unsigned char table_changed_client_mask [CLIENT_MASK_SIZE]; + + /* Per client mask indicating that all delete-pending entries + ** have been deleted from the AVL tree. + */ + unsigned char table_purged_client_mask [CLIENT_MASK_SIZE]; + + /* For NSF tables the flag indicating that the table needs to + ** be synchronized to the backup manager. + */ + unsigned int nsf_table_changed_flag; + + /* For NSF AVL trees the flag indicates that the AVL tree needs to + ** be purged on the backup manager + */ + unsigned int nsf_table_purge_flag; + + /* For writable tables this is the schema size. + */ + unsigned int schema_size; + + /* For writable tables this is a pointer to the schema. + */ + char *schema; + + + /******************************************************** + ** The following information is used only for debugging. + ********************************************************/ + + /* Pointer for linking the nodes inside the sorted list. + */ + struct dataTableNode_s *next_sorted; + + /* Number of read accesses to this table. + ** This includes get, getNext, getNextChanged operations. + */ + unsigned long long num_reads; + + /* Number of write accesses to this table. + ** This includes Set, Insert, Delete operations. + */ + unsigned long long num_writes; + + /* The overall memory size of this data table, including the control overhad. + */ + unsigned int total_memory_size; + + /* For AVL tables this is the size of the index field. + */ + int key_size; + + /* For AVL tables this is the number of times the table-purge action + ** happened for this table. The table-purge action deletes all entries + ** from the table that are in delete-pending state. + */ + int num_purges; + +} dataTableNode_t; + + /******************************************************* + ** Synchronization messages between Manager and + ** Backup managed in the Non-Stop-Forwarding environment. + ********************************************************/ +#define SYNC_MSG_DATA 1 +#define SYNC_MSG_ACK 2 +#define SYNC_MSG_MISS 3 + +/* Sync message header. +*/ +typedef struct +{ + unsigned long long seq; + unsigned short msg_size; + unsigned short msg_type; /* SYNC_MSG_DATA/ACK/MISS */ + unsigned char first_trans; /* 0 or 1-First Transaction */ + unsigned char ack_request; /* 0 or 1-Transmit ACK */ + unsigned char pad1, pad2; /* Pad the header to a four-byte boundary. */ +} nsf_sync_msg_t; + +#define SYNC_IE_SET 1 +#define SYNC_IE_DELETE 2 +#define SYNC_IE_PURGE 3 +#define SYNC_IE_NOOP 4 + +/* Information Element Header +*/ +typedef struct +{ + unsigned short size; /* Size of the whole IE */ + unsigned short segment_size; /* Size of the data in the IE */ + unsigned int record_offset; /* Where to copy the data in the DB record */ + unsigned char cmd; /* SYNC_IE_SET/DELETE/PURGE */ + unsigned char first_seg; /* 0 or 1-First Segment */ + unsigned char last_seg; /* 0 or 1-Last Segment */ + unsigned char pad1; + unsigned char table_name [SYNCDB_TABLE_NAME_SIZE]; +} nsf_ie_t; + +/* NSF State Information. +*/ + +/* Number of buffers the sender can send before asking for ACK. +*/ +#define SYNCDB_MAX_NSF_PENDING_BUFFERS 10 + +/* Number of seconds the sender waits for an ACK reply before +** retransmitting all unacked packets. +*/ +#define SYNCDB_ACK_TIMEOUT 5 + +/* Number of seconds the sender waits for additional data before +** sending an ACK request. +*/ +#define SYNCDB_EMPTY_ACK_TIMEOUT 1 + +typedef struct +{ + unsigned int sync_sender; /* 1-Sync Sender, 0-Sync Receiver */ + + /* Sender State + */ + unsigned long long tx_seq; /* Transmit Sequence Number */ + unsigned int last_tx_time; /* UP Time when last message was sent */ + unsigned int last_ack_time; /* UP Time when last ACK request was sent */ + unsigned int ack_pending; /* 1-waiting for ack */ + unsigned long long expected_ack_sequence; /* ACK reply should contain this number */ + + /* Messages that have been sent, but not acknowledged. + */ + unsigned char *tx_buffers[SYNCDB_MAX_NSF_PENDING_BUFFERS]; + unsigned int tx_buffer_head; + unsigned int tx_buffer_tail; + + /* Receiver State + */ + unsigned long long rx_seq; /* RX Sequence Number */ + unsigned char *record_buf; /* Temporary storage to reassemble the database record */ +} nsf_state_t; + + /******************************************************** + ** The following information is used only for debugging. + ********************************************************/ +typedef struct +{ + /* Global Client Statistics. + */ + unsigned int num_clients; + + /* Global Table Statistics. + */ + unsigned int num_tables; /* Number of data tables */ + unsigned int num_record_tables; /* Number of data tables of type 'Record' */ + unsigned int num_storable_tables; /* Number of data tables of type 'Storable-Record' */ + unsigned int num_queues; /* Number of data tables of type 'Queue' */ + unsigned int num_avl_trees; /* Number of data tables of type 'AVL Tree' */ + + /* Number of allocated bytes for all tables and for each table type. + ** The size includes control overhead. + */ + unsigned int num_tables_size; + unsigned int num_record_tables_size; + unsigned int num_storable_tables_size; + unsigned int num_queues_size; + unsigned int num_avl_trees_size; + + /* This is the total number of commands received on the socket. + */ + unsigned long long num_commands; + + /* Total number of messages received from the syncdb agent and + ** sent to the syncdb agent. + */ + unsigned long long num_rx_agent_msgs; + unsigned long long num_tx_agent_msgs; + + /* The following statistics are counters for each command type. + */ + unsigned long long num_get_commands; + unsigned long long num_field_get_commands; + unsigned long long num_getNext_commands; + unsigned long long num_getNextChanged_commands; + unsigned long long num_insert_commands; + unsigned long long num_delete_commands; + unsigned long long num_set_commands; + unsigned long long num_nsf_sync_mode_commands; + + unsigned int num_tableCreate_commands; + unsigned int num_tableDelete_commands; + unsigned int num_tablePurge_commands; + unsigned int num_tableStore_commands; + unsigned int num_tableChangeNotify_commands; + unsigned int num_tableStatus_commands; + + unsigned int num_clientRegister_commands; + unsigned int num_clientStatusGet_commands; + unsigned long long num_debug_commands; +}globalSyncdbStats_t; + +/* AVL Record control data. +** This information is added to the end of each AVL node. +*/ +typedef struct +{ + /* This flag indicates that the entry has been deleted, but + ** some applications have not processed the delete change + ** notification. + */ + int delete_pending; + + /* Flag indicating that this node needs to be synchronized to + ** the backup manager. + */ + int nsf_node_changed_flag; + + /* Clients that have not invoked a get, getNext, or getNextChanged function + ** for this record since this record was added or changed. + */ + unsigned char changed_mask [CLIENT_MASK_SIZE]; + void * next; /* Needed by the AVL utility */ +} syncdbAvlNodeCtrl_t; + +void syncdb_main (char *path); + +/* Utility Functions. +*/ +void syncdb_database_store (dataTableNode_t *data_table, + char *file_name); +void syncdb_database_read (dataTableNode_t *data_table); + +/* Debug Logging API functions. +*/ +void syncdbLogLevelGet (void); +void syncdbDebugMsgLog (void); +void syncdbClientRegisterMsgLog (int pid, int client_id, int err_code); +void syncdbClientStatusMsgLog (int pid, + int client_id, + int target_client, + int err_code); +void syncdbTableChangeNotifyMsgLog (int pid, + int client_id, + char *table_name, + int err_code); +void syncdbTableStatusGetMsgLog (int pid, + int client_id, + int num_tables, + int err_code); +void syncdbAvlTableCreateMsgLog (int pid, + int client_id, + char *table_name, + int err_code); +void syncdbRecordTableCreateMsgLog (int pid, + int client_id, + char *table_name, + int err_code); +void syncdbTableDeleteMsgLog (int pid, + int client_id, + char *table_name, + int err_code); +void syncdbTableStoreMsgLog (int pid, + int client_id, + char *table_name, + int err_code); +void syncdbInsertMsgLog (int pid, + int client_id, + char *table_name, + int err_code); +void syncdbDeleteMsgLog (int pid, + int client_id, + char *table_name, + int err_code); +void syncdbSetMsgLog (int pid, + int client_id, + char *table_name, + int err_code); +void syncdbFieldSetMsgLog (int pid, + int client_id, + char *table_name, + int offset, + int size, + int err_code); + +void syncdbGetMsgLog (int pid, + int client_id, + char *table_name, + int err_code); + +void syncdbFieldGetMsgLog (int pid, + int client_id, + char *table_name, + int offset, + int size, + int err_code); + +void syncdbGetNextMsgLog (int pid, + int client_id, + char *table_name, + int err_code); + +void syncdbGetNextChangedMsgLog (int pid, + int client_id, + char *table_name, + int err_code); + + + +#endif /* SYNCDB_H_INCLUDED */ + diff --git a/pde-test-host/pde-test-host/include/brcm_syncdb_api.h b/pde-test-host/pde-test-host/include/brcm_syncdb_api.h new file mode 100755 index 0000000..e44edd7 --- /dev/null +++ b/pde-test-host/pde-test-host/include/brcm_syncdb_api.h @@ -0,0 +1,387 @@ +/********************************************************************* + * + * Copyright: (c) 2017 Broadcom. + * Broadcom Proprietary and Confidential. All rights reserved. + * + *********************************************************************/ + +#ifndef SYNCDB_API_H_INCLUDED +#define SYNCDB_API_H_INCLUDED + +#include + +/* Maximum size of the message buffer between the SyncDB process and the +** SyncDB Agent. The actual message size may be smaller, and is limited by +** the transport message size. +**/ +#define SYNCDB_AGENT_MAX_MSG_SIZE (8000) + +/* Maximum size of the text string that uniquely identifies +** a database table. The size includes the 0 terminator. +** This value must be divisible by 2. +*/ +#define SYNCDB_TABLE_NAME_SIZE 32 + +/* Maximum length for string fields used by syncdb. This includes +** client names, file names and various descriptions. +*/ +#define SYNCDB_MAX_STR_LEN 256 + +/* Maximum size of a single data record. In case of AVL trees and Queues +** this is the maximum size of each AVL or Queue node. +*/ +#define SYNCDB_RECORD_MAX_SIZE (1024*64) + +/* Supported Data Table Types. +*/ +#define SYNCDB_TABLE_TYPE_RECORD 0 +#define SYNCDB_TABLE_TYPE_STORABLE_RECORD 1 +#define SYNCDB_TABLE_TYPE_AVL_TREE 2 +#define SYNCDB_TABLE_TYPE_QUEUE 3 + +/* Return Codes from the syncdb API functions. +*/ +#define SYNCDB_OK (0) +#define SYNCDB_ERROR (-1) /* General Error */ +#define SYNCDB_MAX_CLIENTS (-2) /* Reached maximum number of clients */ +#define SYNCDB_DUPNAME (-3) /* Table exists with duplicate name */ +#define SYNCDB_NO_TABLE (-4) /* Specified table does not exist */ +#define SYNCDB_FULL (-5) /* Specified table is full */ +#define SYNCDB_SIZE (-6) /* Specified record size is invalid for this table. */ +#define SYNCDB_NOT_FOUND (-7) /* Specified record is not in the table. */ +#define SYNCDB_SCHEMA_ERROR (-8) /* Schema validation error */ +#define SYNCDB_ENTRY_EXISTS (-9) /* AVL entry with the specified key already exists */ + +/******** Data Table Status. +** The status is a bit mask returned by the syncdbTableStatusGet() function. +** The status is maintained per client. +********/ + +/* Specified Table Exist +** If this bit is not set to 1 then all other bits are meaningless. +*/ +#define SYNCDB_TABLE_STAT_EXISTS (1 << 0) + +/* Changes pending for this client. (Cleared on Read) +** This bit is set whenever something changes in the table. The bit is cleared +** when the syncdbTableStatusGet() function is invoked by the client for the table. +** When a client gets a table change notification, this bit can be used to determine +** which table has changed. However the client does not need to be registered for +** change notifications. The bit is set for all clients when the table changes. +*/ +#define SYNCDB_TABLE_STAT_CHANGED (1 << 1) + +/* AVL Tree Purged (Cleared on Read) +** This bit indicates that all delete-pending entries have been removed from the +** AVL tree since the last call to the syncdbTableStatusGet() function. +** This means that some record delete notifcations may have been missed by this client. +** The client needs to completely resynchronize with the AVL tree if it needs to know +** the exact content. +** If the table is not an AVL tree then this bit is always set to 0. +*/ +#define SYNCDB_TABLE_STAT_AVL_TREE_PURGED (1 << 2) + +/* New Table (Cleared on Read) +** This bit indicates that the syncdbTableStatusGet() function is called for +** the first time since the table has been created. +** This flag can be used to detect that a table has been deleted and recreated. +** Normally applications do not delete tables, even when they are restarted. If +** a table needs to be deleted then all applications using this table should be +** restarted. +*/ +#define SYNCDB_TABLE_STAT_NEW_TABLE (1 << 3) + +/******** Data Table Creation Flags +** The flags specified on the table create call. +** The flags is a bit mask returned by the syncdbTableStatusGet() function. +********/ +/* +** This table can be stored in a file. +** When this flag is set the table creation function must be given the schema and +** the schema size. +*/ +#define SYNCDB_TABLE_FLAG_STORABLE (1 << 0) + +/* This table is copied to NVRAM when the table-store command is received. +** The flag is allowed only if the SYNCDB_TABLE_FLASG_STORABLE is also set. +*/ +#define SYNCDB_TABLE_FLAG_NVRAM (1 << 1) + +/* If this flag is enabled then the syncdb tries to populate the table +** from a file when creating the table. +** The flag is allowed only if the SYNCDB_TABLE_FLAG_STORABLE is also set. +*/ +#define SYNCDB_TABLE_FLAG_FILE_LOAD (1 << 2) + + +/* When this flag is set, the syncdbInsert() function returns an error if an +** entry with the specified key already exists. When this flag is not set the +** old entry is overwriten with the new content. +*/ +#define SYNCDB_TABLE_FLAG_EXISTS (1 << 3) + +/* When this flag is set, the content of the table is synchronized with the backup +** manager. On non-stacking platform the flag has no effect. +** Applications that use SyncDB for the Non Stop Forwarding feature should store +** the data in the datble using the big-endian format. +*/ +#define SYNCDB_TABLE_FLAG_NSF (1 << 4) + +/* syncdb Client Handle. +*/ +typedef struct +{ + int cmd_socket; + int notify_socket; + int client_id; + pthread_mutex_t client_lock; +} syncdbClientHandle_t; + +/* Data Table Status +*/ +typedef struct +{ + char table_name [SYNCDB_TABLE_NAME_SIZE]; + + /* The version of the table. This information can be used by processes + ** to decide whether the table is compatible with the process. + */ + unsigned int table_version; + + /* Flags specified on table creation. SYCNDB_TABLE_FLAG_STORABLE and others... + */ + unsigned int table_flags; + + /* Bit Mask. See description for SYNCDB_TABLE_STAT_EXISTS and others... + */ + unsigned int table_status; + + /* If the table exists then this specifies the table type. + ** The types are SYNCDB_TABLE_TYPE_RECORD,... + */ + int table_type; + + /* Number of records in the table. + ** Valid only for Queues and AVL Trees + */ + int num_elements; + + /* Number of records that are not in delete-pending state. + ** This parameter is valid only for AVL trees. + */ + int num_non_deleted_elements; +} syncdbDataTableStatus_t; + +/* Client Table Status. +*/ +typedef struct +{ + int client_id; /* syncdb client ID of the client for which to retrieve the status */ + char client_description [SYNCDB_MAX_STR_LEN]; + int client_pid; /* Linux Process ID for this client */ + int num_commands; /* Total number of commands issued by this client */ + int num_table_change_events; /* Total number of table-change notifications sent to the client */ + int num_table_purges; /* Number of AVL tree purge events sent to the client */ +} syncdbClientStatus_t; + +/******************************** +** Storable Record Schema +********************************/ + +/* The AVL trees and records can be stored in a file system using JSON notation. +** In order to store information in the file system the table creator must tell syncdb how +** the data is formatted. Also to facilitate data format changes the table creator must +** tell syncdb the default values of fields that are not present in the file. +*/ + +/* The schema for storable records is also defined using JSON format. +** This compiler constant defines the maximum length of the schema. +** The constant may be changed to be smaller than the maximum record size, but +** never bigger. +*/ +#define SYNCDB_JSON_MAX_SCHEMA_SIZE (SYNCDB_RECORD_MAX_SIZE) + +/* The syncdb supports the following JSON data types: +** SYNCDB_JSON_NUMBER - A numeric value. Syncdb supports only unsigned integers. +** SYNCDB_JSON_STRING - Zero-terminated array of characters. +** SYNCDB_JSON_ARRAY - Syncdb supports only arrays of bytes. The default value is 0. +** +** SYNCDB Data Type Limitations: +** The syncdb supports only a subset of JSON data types. +** The most important limitation is the limited support for arays. Arrays are difficult +** to handle during data format migration, so should be avoided when defining storable records. +** Syncdb does support arrays of bytes. The table creator cannot provide default values for +** the byte arrays. The default for array content is always zero. +** +** The syncdb supports only unsigned integer values for SYNCDB_JSON_NUMBER type. +** The supported integer sizes are 1, 2, 4, and 8 bytes. +** Floating point numbers and exponential notation is not supported. +** Signed integers are also not supported. If a signed integer is used in the node +** definition then the data migration may not work properly. +** +** The syncdb also does not support "true", "false", and "null" values. These can be represented +** with an integer. +*/ +typedef enum +{ + SYNCDB_JSON_NUMBER = 1, + SYNCDB_JSON_STRING = 2, + SYNCDB_JSON_ARRAY = 3 +} syncdbJsonDataType_e; + +typedef struct syncdbJsonNode_s +{ + syncdbJsonDataType_e data_type; + + /* The uniqe identifier for this variable. The data_name is used to + ** match fields when performing version migration. All names within + ** the element must be unique. A good policy is to use the fully + ** qualified C field name, such as "element.key.k1" + ** There is no limit on the size of the name field, other than the + ** overall schema size limit. + */ + char *data_name; + + /* Offset of this element from the beginning of the data buffer. + ** Note that if an element is a member of a structure within another + ** structure then the offset of the nested structure needs to be added + ** to the offset of the variable. + */ + unsigned int data_offset; + + /* The size of this data element in bytes. + */ + unsigned int data_size; + + union { + unsigned long long default_number; /* Default value for SYNCDB_JSON_NUMBER object. */ + char *default_string; /* Default value for SYNCDB_JSON_STRING object */ + } val; + +} syncdbJsonNode_t; + +/* The following errors may be reported during schema validation. +*/ +typedef enum +{ + SYNCDB_SCHEMA_OK = 0, /* No error */ + SYNCDB_SCHEMA_TOO_BIG = 1, /* Schema node offset plus size is larger than data element */ + SYNCDB_SCHEMA_OVERLAP = 2, /* Schema nodes overlap each other. */ + SYNCDB_SCHEMA_TOO_SHORT = 3, /* Data element has 8 or more bytes beyond last schema node */ + SYNCDB_SCHEMA_GAP = 4, /* Two schema nodes have an 8 or more byte gap between them */ + SYNCDB_SCHEMA_INT_OVERFLOW = 5, /* Default value for an integer does not fit into size */ + SYNCDB_SCHEMA_STRING_OVERFLOW = 6, /* Default value for a string does not fit into size */ + SYNCDB_SCHEMA_INT_SIZE = 7, /* Integer size is not 1, 2, 4, or 8 */ + SYNCDB_SCHEMA_TYPE = 8, /* Data type is not Number, String or Array. */ + SYNCDB_SCHEMA_NO_ZERO_OFFSET = 9, /* No node with offset set to 0. */ + SYNCDB_SCHEMA_ZERO_SIZE = 10, /* Found an element with size equal to 0 */ + SYNCDB_SCHEMA_DUP_NAME = 11 /* The element has the same name as another element in the schema */ +} syncdbSchemaError_e; + +/******************************** +** syncdb API Functions +*********************************/ +int syncdbUtilSchemaCreate (syncdbJsonNode_t *element_node, + unsigned int node_schema_size, + char *schema_buf, + unsigned int buf_size, + unsigned int *schema_size, + unsigned int data_element_size, + syncdbSchemaError_e *schema_error + ); + +int syncdbClientRegister (char *client_name, + syncdbClientHandle_t *client_id, char *path); + +int syncdbClientStatusGet (syncdbClientHandle_t *client_id, + syncdbClientStatus_t *client_status); + +int syncdbTableStore (syncdbClientHandle_t *client_id, + char *table_name, + unsigned int nvram); + +int syncdbTableChangeCheck (syncdbClientHandle_t *client_id, + int timeout_secs); + +int syncdbTableChangeNotify (syncdbClientHandle_t *client_id, + char *table_name); + +int syncdbTableStatusGet (syncdbClientHandle_t *client_id, + int num_tables, + syncdbDataTableStatus_t *table_list); + +int syncdbAvlTableCreate (syncdbClientHandle_t *client_id, + char *table_name, + unsigned int table_version, + unsigned int max_elements, + unsigned int max_live_elements, + unsigned int node_size, + unsigned int key_size, + unsigned int flags, + char * schema, + unsigned int schema_size); + +int syncdbRecordTableCreate (syncdbClientHandle_t *client_id, + char *table_name, + unsigned int table_version, + unsigned int node_size, + unsigned int flags, + char * schema, + unsigned int schema_size); + +int syncdbTableDelete (syncdbClientHandle_t *client_id, + char *table_name); + +int syncdbInsert (syncdbClientHandle_t *client_id, + char *table_name, + void *element, + unsigned int size); + +int syncdbDelete (syncdbClientHandle_t *client_id, + char *table_name, + void *element, + unsigned int size); + +int syncdbSet (syncdbClientHandle_t *client_id, + char *table_name, + void *element, + unsigned int size); + +int syncdbFieldSet (syncdbClientHandle_t *client_id, + char *table_name, + void *element, + unsigned int size, + unsigned int field_offset, + unsigned int field_size); + +int syncdbGet (syncdbClientHandle_t *client_id, + char *table_name, + void *element, + unsigned int size, + int *delete_pending); + +int syncdbFieldGet (syncdbClientHandle_t *client_id, + char *table_name, + void *element, + unsigned int size, + unsigned int field_offset, + unsigned int field_size, + int flags_unchanged, + int *delete_pending); + +int syncdbGetNext (syncdbClientHandle_t *client_id, + char *table_name, + void *element, + unsigned int size, + int *delete_pending); +int syncdbGetNextChanged (syncdbClientHandle_t *client_id, + char *table_name, + void *element, + unsigned int size, + int *delete_pending); +int syncdbNsfModeSet (syncdbClientHandle_t *client_id, + unsigned int sync_mode, + unsigned int max_msg_size); + +#endif /* SYNCDB_API_H_INCLUDED */ + diff --git a/pde-test-host/pde-test-host/include/brcm_syncdb_msg.h b/pde-test-host/pde-test-host/include/brcm_syncdb_msg.h new file mode 100755 index 0000000..4759c9a --- /dev/null +++ b/pde-test-host/pde-test-host/include/brcm_syncdb_msg.h @@ -0,0 +1,172 @@ +/********************************************************************* + * + * Copyright: (c) 2017 Broadcom. + * Broadcom Proprietary and Confidential. All rights reserved. + * + *********************************************************************/ + +#ifndef SYNCDB_MSG_H_INCLUDED +#define SYNCDB_MSG_H_INCLUDED + +#include +#include + +#define SYNCDB_CMD_BUFF_SIZE 512 +#define SYNCDB_FILE_PATH_BUFF_SIZE 256 + +/* The syncdb process command socket name. +*/ +#define SYNCDB_SERVER_SOCKET "/syncdb-server-sock" + +/* The socket for sending from the SyncDB process to the +** Syncdb agent running in the swithdrvr process. +*/ +#define SYNCDB_TO_AGENT_SOCKET "/syncdb-to-agent-sock" + +/* The socket for sending from the SyncDB agent to the +** Syncdb process. +*/ +#define SYNCDB_FROM_AGENT_SOCKET "/syncdb-from-agent-sock" + +/* Maximum size of the command message on the socket. +*/ +#define SYNCDB_MSG_MAX_SIZE (SYNCDB_RECORD_MAX_SIZE + sizeof(syncdbCmdMsg_t)) + +typedef enum +{ + SYNCDB_REPLY = 0, + SYNCDB_DEBUG = 1, + SYNCDB_CLIENT_REGISTER = 2, + SYNCDB_CLIENT_STATUS = 3, + SYNCDB_AVL_TABLE_CREATE = 4, + SYNCDB_QUEUE_TABLE_CREATE = 5, + SYNCDB_RECORD_TABLE_CREATE = 6, + SYNCDB_STORABLE_RECORD_TABLE_CREATE = 7, + SYNCDB_TABLE_DELETE = 8, + SYNCDB_TABLE_CHANGE_NOTIFY = 9, + SYNCDB_TABLE_STATUS = 10, + SYNCDB_TABLE_STORE = 11, + SYNCDB_INSERT = 12, + SYNCDB_DELETE = 13, + SYNCDB_GET = 14, + SYNCDB_FIELD_GET = 15, + SYNCDB_GETNEXT = 16, + SYNCDB_GETNEXT_CHANGED = 17, + SYNCDB_SET = 18, + SYNCDB_FIELD_SET = 19, + SYNCDB_NSF_SYNC_ENABLE = 20 +} syncdbMsg_t; + +/* Message structure definitions. +*/ + +/* Client Registration Message. +*/ +typedef struct +{ + pid_t pid; + char client_socket_name [SYNCDB_MAX_STR_LEN]; + char client_notify_socket_name [SYNCDB_MAX_STR_LEN]; + char client_description [SYNCDB_MAX_STR_LEN]; + +} syncdbClientRegisterMsg_t ; + +/* Table Creation Message. +*/ +typedef struct +{ + char table_name [SYNCDB_TABLE_NAME_SIZE]; + unsigned int table_version; + unsigned int max_elements; /* Only meaningful for AVL and Queue */ + unsigned int max_live_elements; /* Only meaningful for AVL */ + unsigned int node_size; + unsigned int key_size; /* Only meaningful for AVL */ + unsigned int flags; + unsigned int schema_size; +} syncdbTableCreateMsg_t; + +/* Table Change Notification Message +*/ +typedef struct +{ + char table_name [SYNCDB_TABLE_NAME_SIZE]; +} syncdbTableChangeNotifyMsg_t; + +/* Table Status Get Message +*/ +typedef struct +{ + int num_tables; +} syncdbTableStatusGetMsg_t; + +/* Message used for Set/Insert/Delete commands. +*/ +typedef struct +{ + char table_name [SYNCDB_TABLE_NAME_SIZE]; + unsigned int size; + unsigned int field_offset; + unsigned int field_size; +} syncdbGenericSetMsg_t; + +/* Message used for Get/GetNext/GetNextChanged commands. +** The message is used for requests and replies. +*/ +typedef struct +{ + char table_name [SYNCDB_TABLE_NAME_SIZE]; + unsigned int size; + unsigned int field_offset; + unsigned int field_size; + int flags_unchanged; + int delete_pending; /* Only used for replies */ +} syncdbGenericGetMsg_t; + +/* Table Delete Message +*/ +typedef struct +{ + char table_name [SYNCDB_TABLE_NAME_SIZE]; +} syncdbTableDeleteMsg_t; + +/* Table Store Message +*/ +typedef struct +{ + char table_name [SYNCDB_TABLE_NAME_SIZE]; + unsigned int all_tables; + unsigned int nvram; +} syncdbTableStoreMsg_t; + +/* NSF Sync Mode Message. +*/ +typedef struct +{ + unsigned int sync_mode; + unsigned int max_sync_msg_size; +} syncdbNsfSyncModeMsg_t; + +/* Message header for communicating between the clients and the syncdb server. +*/ +typedef struct +{ + syncdbMsg_t message_type; + unsigned int client_id; /* Valid only for requests and client register replies */ + int rc; /* Valid only for reply messages */ + union + { + syncdbClientRegisterMsg_t registerMsg; + syncdbTableCreateMsg_t tableCreateMsg; + syncdbGenericSetMsg_t genericSetMsg; + syncdbGenericGetMsg_t genericGetMsg; + syncdbTableChangeNotifyMsg_t tableChangeNotifyMsg; + syncdbTableStatusGetMsg_t tableStatusGetMsg; + syncdbTableDeleteMsg_t tableDeleteMsg; + syncdbTableStoreMsg_t tableStoreMsg; + syncdbNsfSyncModeMsg_t nsfSyncMsg; + }msg; +} syncdbCmdMsg_t; + + +#endif /* SYNCDB_MSG_H_INCLUDED */ + diff --git a/pde-test-host/pde-test-host/include/compiler.h b/pde-test-host/pde-test-host/include/compiler.h new file mode 100755 index 0000000..d346eb5 --- /dev/null +++ b/pde-test-host/pde-test-host/include/compiler.h @@ -0,0 +1,655 @@ +/* + * $Id: compiler.h,v 1.42 Broadcom SDK $ + * $Copyright: (c) 2018 Broadcom. + * Broadcom Proprietary and Confidential. All rights reserved.$ + * + * Compiler Specific defines and options + */ + +#ifndef _SAL_COMPILER_H +#define _SAL_COMPILER_H + +/* + * Define attributes according to compiler. + * Currently we have used GNU C, Diab Data, and Borland compilers. + */ + +#define COMPILER_HAS_CONST +#define COMPILER_HAS_STATIC + +#ifndef __KERNEL__ +#define COMPILER_HAS_DOUBLE +#endif + +/* + * Return a string containing the current FILE:LINE location in the code. + * + */ +#ifndef FILE_LINE_STRING + +#define __STRINGIFY(x) #x +#define _STRINGIFY(x) __STRINGIFY(x) + +#define FILE_LINE_STRING() (__FILE__ ":" _STRINGIFY(__LINE__)) + +#endif /* FILE_LINE_STRING */ + + +#if defined(__GNUC__) && !defined(__PEDANTIC__) + +#define COMPILER_HAS_LONGLONG +#if defined(VXWORKS) && ((CPU == PPC860) || (CPU == PPC603) || (CPU == PPC32)) +/* + * WRS T2 (Cygnus 2.7.2) PPC compiler can't handle 64-bit properly. + * It generates bad code for shift by 32. It also generates false + * "variable might be used initialized" warnings for COMPILER_ZERO. + */ +#if (VX_VERSION == 55) || (VX_VERSION >= 62) +# define COMPILER_HAS_LONGLONG_SHIFT +#else +# undef COMPILER_HAS_LONGLONG_SHIFT +#endif +#else +# define COMPILER_HAS_LONGLONG_SHIFT +#endif +#define COMPILER_HAS_LONGLONG_ADDSUB +#define COMPILER_HAS_LONGLONG_MUL +#define COMPILER_HAS_LONGLONG_DIV +#define COMPILER_HAS_LONGLONG_ANDOR +#define COMPILER_HAS_LONGLONG_COMPARE + +#if ((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100) + __GNUC_PATCHLEVEL__) >= 30201 +/* gcc 3.2.1 is the earliest version known to support the format attribute + when applied to function pointers. gcc 3.0.0 is known to *not* support + this. */ +#define COMPILER_HAS_FUNCTION_POINTER_FORMAT_ATTRIBUTE +#endif + +#ifndef __STRICT_ANSI__ +#define COMPILER_HAS_INLINE +#endif + +#define COMPILER_ATTRIBUTE(_a) __attribute__ (_a) +#define COMPILER_REFERENCE(_a) ((void)(_a)) +#ifndef FUNCTION_NAME +#define FUNCTION_NAME() (__FUNCTION__) +#endif + +#elif (defined(__DCC__) && (__DCC__ == 1)) && !defined(__PEDANTIC__) + +#define COMPILER_HAS_LONGLONG +#define COMPILER_HAS_LONGLONG_SHIFT +#define COMPILER_HAS_LONGLONG_ADDSUB +#define COMPILER_HAS_LONGLONG_MUL +#define COMPILER_HAS_LONGLONG_DIV +#define COMPILER_HAS_LONGLONG_ANDOR +#define COMPILER_HAS_LONGLONG_COMPARE + +#define COMPILER_ATTRIBUTE(_a) +#define COMPILER_REFERENCE(_a) ((void)(_a)) + +#if (defined(DIAB_VER)) && (DIAB_VER == 4) +/* Older versions of DCC do not support __FUNCTION__ */ +#define FUNCTION_NAME() FILE_LINE_STRING() +#else +#define FUNCTION_NAME() (__FUNCTION__) +#endif + +#else /* !defined(__GNUC__) */ + +#define COMPILER_ATTRIBUTE(_a) +#define COMPILER_REFERENCE(_a) ((void)(_a)) + +#ifndef FUNCTION_NAME +/* + * No portable ANSI method to accomplish this. + * Just return the location in the code instead. + */ +#define FUNCTION_NAME() FILE_LINE_STRING() + +#endif /* FUNCTION_NAME */ + +#endif /* !defined(__GNUC__) */ + +#ifdef SAND_PEDANTIC +#define COMPILER_HAS_LONGLONG +#define COMPILER_HAS_LONGLONG_SHIFT +#define COMPILER_HAS_LONGLONG_ADDSUB +#define COMPILER_HAS_LONGLONG_MUL +#define COMPILER_HAS_LONGLONG_DIV +#define COMPILER_HAS_LONGLONG_ANDOR +#define COMPILER_HAS_LONGLONG_COMPARE +/* + * Relevant for logging facilities (BSL, ...) + * E.g. Without this definition LOG_ERROR instead of FUNCTION name prints C-code location and line number + */ +#ifdef FUNCTION_NAME +#undef FUNCTION_NAME +#endif +#define FUNCTION_NAME() (__FUNCTION__) + +#endif + +/* GreenHills compiler */ +#ifdef GHS +#define COMPILER_HAS_LONGLONG +#define COMPILER_HAS_LONGLONG_SHIFT +#define COMPILER_HAS_LONGLONG_ADDSUB +#define COMPILER_HAS_LONGLONG_MUL +#define COMPILER_HAS_LONGLONG_DIV +#define COMPILER_HAS_LONGLONG_ANDOR +#define COMPILER_HAS_LONGLONG_COMPARE + +/* GreenHills compiler has __FUNCTION__ built-in macro not __func__ */ +#define __func__ __FUNCTION__ +#endif + +/* + * __attribute__ for function pointers + */ +#ifdef COMPILER_HAS_FUNCTION_POINTER_FORMAT_ATTRIBUTE +#define COMPILER_ATTRIBUTE_FUNCTION_POINTER(_a) COMPILER_ATTRIBUTE(_a) +#else +#define COMPILER_ATTRIBUTE_FUNCTION_POINTER(_a) +#endif + + +#ifdef __PEDANTIC__ +#define COMPILER_STRING_CONST_LIMIT 509 +#endif + +/* + * Compiler overrides that can be configured in Make.local + */ +#ifdef COMPILER_OVERRIDE_NO_LONGLONG +#undef COMPILER_HAS_LONGLONG +#undef COMPILER_HAS_LONGLONG_SHIFT +#undef COMPILER_HAS_LONGLONG_ADDSUB +#undef COMPILER_HAS_LONGLONG_MUL +#undef COMPILER_HAS_LONGLONG_DIV +#undef COMPILER_HAS_LONGLONG_ANDOR +#undef COMPILER_HAS_LONGLONG_COMPARE +#endif + +#ifdef COMPILER_OVERRIDE_NO_DOUBLE +#undef COMPILER_HAS_DOUBLE +#endif + +#ifdef COMPILER_OVERRIDE_NO_INLINE +#undef COMPILER_HAS_INLINE +#endif + +#ifdef COMPILER_OVERRIDE_NO_CONST +#undef COMPILER_HAS_CONST +#endif + +#ifdef COMPILER_OVERRIDE_NO_STATIC +#undef COMPILER_HAS_STATIC +#endif + +/* + * 64-bit word order + */ + +#ifdef __BORLAND__ +/* The Borland cpp does not expand correctly in the macros below...sigh */ +static int u64_MSW = 1; +static int u64_LSW = 0; +#else +# ifdef BE_HOST +# define u64_MSW 0 +# define u64_LSW 1 +# else /* LE_HOST */ +# define u64_MSW 1 +# define u64_LSW 0 +# endif /* LE_HOST */ +#endif /* __BORLAND__ */ + +/* + * 64-bit type + */ + +#ifdef LONGS_ARE_64BITS + +#define COMPILER_64BIT +#define COMPILER_UINT64 unsigned long +#define COMPILER_INT64 long +#define u64_H(v) (((uint32 *) &(v))[u64_MSW]) +#define u64_L(v) (((uint32 *) &(v))[u64_LSW]) +#define COMPILER_64_INIT(_hi, _lo) ( (((long) (_hi)) << 32) | (_lo)) + +#else /* !LONGS_ARE_64BITS */ + +#ifdef COMPILER_HAS_LONGLONG + +#define COMPILER_64BIT +#define COMPILER_UINT64 unsigned long long +#define COMPILER_INT64 long long +#define u64_H(v) (((uint32 *) &(v))[u64_MSW]) +#define u64_L(v) (((uint32 *) &(v))[u64_LSW]) +#define COMPILER_64_INIT(_hi, _lo) ( (((long long) (_hi)) << 32) | (_lo)) + +#else /* !COMPILER_HAS_LONGLONG */ +typedef struct sal_uint64_s { unsigned int u64_w[2]; } sal_uint64_t; +typedef struct sal_int64_s { int u64_w[2]; } sal_int64_t; + +#define COMPILER_UINT64 sal_uint64_t +#define COMPILER_INT64 sal_int64_t +#define u64_H(v) ((v).u64_w[u64_MSW]) +#define u64_L(v) ((v).u64_w[u64_LSW]) + +#ifdef BE_HOST +#define COMPILER_64_INIT(_hi, _lo) { { _hi, _lo } } +#else +#define COMPILER_64_INIT(_hi, _lo) { { _lo, _hi } } +#endif + +#endif /* !COMPILER_HAS_LONGLONG */ +#endif /* LONGS_ARE_64BITS */ + +/* + * 32-/64-bit type conversions + */ + +#ifdef COMPILER_HAS_LONGLONG_SHIFT + +#define COMPILER_64_TO_32_LO(dst, src) ((dst) = (uint32) (src)) +#define COMPILER_64_TO_32_HI(dst, src) ((dst) = (uint32) ((src) >> 32)) +#define COMPILER_64_HI(src) ((uint32) ((src) >> 32)) +#define COMPILER_64_LO(src) ((uint32) (src)) +#define COMPILER_64_ZERO(dst) ((dst) = 0) +#define COMPILER_64_IS_ZERO(src) ((src) == 0) + + +#define COMPILER_64_SET(dst, src_hi, src_lo) \ + ((dst) = (((uint64) ((uint32)(src_hi))) << 32) | ((uint64) ((uint32)(src_lo)))) + +#define COMPILER_64_COPY(dst, src) \ + (dst = src) + + +#else /* !COMPILER_HAS_LONGLONG_SHIFT */ + +#define COMPILER_64_TO_32_LO(dst, src) ((dst) = u64_L(src)) +#define COMPILER_64_TO_32_HI(dst, src) ((dst) = u64_H(src)) +#define COMPILER_64_HI(src) u64_H(src) +#define COMPILER_64_LO(src) u64_L(src) +#define COMPILER_64_ZERO(dst) (u64_H(dst) = u64_L(dst) = 0) +#define COMPILER_64_IS_ZERO(src) (u64_H(src) == 0 && u64_L(src) == 0) + +#define COMPILER_64_SET(dst, src_hi, src_lo) \ + do { \ + u64_H(dst) = (src_hi); \ + u64_L(dst) = (src_lo); \ + } while (0) + +#define COMPILER_64_COPY(dst, src) \ + do { \ + u64_H(dst) = u64_H(src); \ + u64_L(dst) = u64_L(src); \ + } while (0) + +#endif /* !COMPILER_HAS_LONGLONG_SHIFT */ + +/* + * 64-bit addition and subtraction + */ + +#ifdef COMPILER_HAS_LONGLONG_ADDSUB + +#define COMPILER_64_ADD_64(dst, src) ((dst) += (src)) +#define COMPILER_64_ADD_32(dst, src) ((dst) += (src)) +#define COMPILER_64_SUB_64(dst, src) ((dst) -= (src)) +#define COMPILER_64_SUB_32(dst, src) ((dst) -= (src)) + +#else /* !COMPILER_HAS_LONGLONG_ADDSUB */ + +#define COMPILER_64_ADD_64(dst, src) \ + do { \ + uint32 __t = u64_L(dst); \ + u64_L(dst) += u64_L(src); \ + if (u64_L(dst) < __t) { \ + u64_H(dst) += u64_H(src) + 1; \ + } else { \ + u64_H(dst) += u64_H(src); \ + } \ + } while (0) +#define COMPILER_64_ADD_32(dst, src) \ + do { \ + uint32 __t = u64_L(dst); \ + u64_L(dst) += (src); \ + if (u64_L(dst) < __t) { \ + u64_H(dst)++; \ + } \ + } while (0) +#define COMPILER_64_SUB_64(dst, src) \ + do { \ + uint32 __t = u64_L(dst); \ + u64_L(dst) -= u64_L(src); \ + if (u64_L(dst) > __t) { \ + u64_H(dst) -= u64_H(src) + 1; \ + } else { \ + u64_H(dst) -= u64_H(src); \ + } \ + } while (0) +#define COMPILER_64_SUB_32(dst, src) \ + do { \ + uint32 __t = u64_L(dst); \ + u64_L(dst) -= (src); \ + if (u64_L(dst) > __t) { \ + u64_H(dst)--; \ + } \ + } while (0) + +#endif /* !COMPILER_HAS_LONGLONG_ADDSUB */ + +/* + * 64-bit multiplication + */ + +#if defined COMPILER_HAS_LONGLONG_MUL && ! defined (__KERNEL__) + +#define COMPILER_64_UMUL_32(dst, src) ((dst) *= (src)) + +#else /* !(defined COMPILER_HAS_LONGLONG_MUL && ! defined (__KERNEL__)) */ + +/* Multiply of unsigned 64-bit and unsigned 32-bit integers, no overflow handling */ +#define COMPILER_64_UMUL_32(dst, src) \ + do { \ + uint32 __d[4]; \ + uint32 __s[2]; \ + uint32 __r[4]; \ + uint32 __t[2]; \ + __d[0] = u64_L(dst) & 0xffff; \ + __d[1] = u64_L(dst) >> 16; \ + __d[2] = u64_H(dst) & 0xffff; \ + __d[3] = u64_H(dst) >> 16; \ + __s[0] = (src) & 0xffff; \ + __s[1] = (src) >> 16; \ + __r[0] = __d[0] * __s[0]; \ + __r[1] = __d[1] * __s[0] + __d[0] * __s[1]; \ + __r[2] = __d[2] * __s[0] + __d[1] * __s[1]; \ + __r[3] = __d[3] * __s[0] + __d[2] * __s[1]; \ + __t[0] = __r[1] << 16; \ + __t[1] = __t[0] + __r[0]; \ + COMPILER_64_SET((dst), (__r[3] << 16) + __r[2] + (__r[1] >> 16) + (__t[1] < __t[0] ? 1 : 0), \ + __t[1] \ + ); \ + } while (0); + +#endif /* !COMPILER_HAS_LONGLONG_MUL */ + +/* + * 64-bit logical operations + */ + +#ifdef COMPILER_HAS_LONGLONG_ANDOR + +#define COMPILER_64_AND(dst, src) ((dst) &= (src)) +#define COMPILER_64_OR(dst, src) ((dst) |= (src)) +#define COMPILER_64_XOR(dst, src) ((dst) ^= (src)) +#define COMPILER_64_NOT(dst) ((dst) = ~(dst)) + +#else /* !COMPILER_HAS_LONGLONG_ANDOR */ + +#define COMPILER_64_AND(dst, src) \ + do { \ + u64_H((dst)) &= u64_H((src)); \ + u64_L((dst)) &= u64_L((src)); \ + } while (0) +#define COMPILER_64_OR(dst, src) \ + do { \ + u64_H((dst)) |= u64_H((src)); \ + u64_L((dst)) |= u64_L((src)); \ + } while (0) +#define COMPILER_64_XOR(dst, src) \ + do { \ + u64_H((dst)) ^= u64_H((src)); \ + u64_L((dst)) ^= u64_L((src)); \ + } while (0) +#define COMPILER_64_NOT(dst) \ + do { \ + u64_H((dst)) = ~u64_H((dst)); \ + u64_L((dst)) = ~u64_L((dst)); \ + } while (0) + +#endif /* !COMPILER_HAS_LONGLONG_ANDOR */ + +#define COMPILER_64_ALLONES(dst) \ + COMPILER_64_ZERO((dst));\ + COMPILER_64_NOT((dst)) + +/* + * 64-bit shift + */ + +#ifdef COMPILER_HAS_LONGLONG_SHIFT + +#define COMPILER_64_SHL(dst, bits) ((dst) <<= (bits)) +#define COMPILER_64_SHR(dst, bits) ((dst) >>= (bits)) + +#define COMPILER_64_BITTEST(val, n) \ + ((((uint64)val) & (((uint64) 1)<<(n))) != ((uint64) 0)) + +#else /* !COMPILER_HAS_LONGLONG_SHIFT */ + +#define COMPILER_64_SHL(dst, bits) \ + do { \ + int __b = (bits); \ + if (__b >= 32) { \ + u64_H(dst) = u64_L(dst); \ + u64_L(dst) = 0; \ + __b -= 32; \ + } \ + u64_H(dst) = (u64_H(dst) << __b) | \ + (__b ? u64_L(dst) >> (32 - __b) : 0); \ + u64_L(dst) <<= __b; \ + } while (0) + +#define COMPILER_64_SHR(dst, bits) \ + do { \ + int __b = (bits); \ + if (__b >= 32) { \ + u64_L(dst) = u64_H(dst); \ + u64_H(dst) = 0; \ + __b -= 32; \ + } \ + u64_L(dst) = (u64_L(dst) >> __b) | \ + (__b ? u64_H(dst) << (32 - __b) : 0); \ + u64_H(dst) >>= __b; \ + } while (0) + +#define COMPILER_64_BITTEST(val, n) \ + ( (((n) < 32) && (u64_L(val) & (1 << (n)))) || \ + (((n) >= 32) && (u64_H(val) & (1 << ((n) - 32)))) ) + +#endif /* !COMPILER_HAS_LONGLONG_SHIFT */ + +/* + * 64-bit compare operations + */ + +#ifdef COMPILER_HAS_LONGLONG_COMPARE + +#define COMPILER_64_EQ(src1, src2) ((src1) == (src2)) +#define COMPILER_64_NE(src1, src2) ((src1) != (src2)) +#define COMPILER_64_LT(src1, src2) ((src1) < (src2)) +#define COMPILER_64_LE(src1, src2) ((src1) <= (src2)) +#define COMPILER_64_GT(src1, src2) ((src1) > (src2)) +#define COMPILER_64_GE(src1, src2) ((src1) >= (src2)) + +#else /* !COMPILER_HAS_LONGLONG_COMPARE */ + +#define COMPILER_64_EQ(src1, src2) (u64_H(src1) == u64_H(src2) && \ + u64_L(src1) == u64_L(src2)) +#define COMPILER_64_NE(src1, src2) (u64_H(src1) != u64_H(src2) || \ + u64_L(src1) != u64_L(src2)) +#define COMPILER_64_LT(src1, src2) (u64_H(src1) < u64_H(src2) || \ + ((u64_H(src1) == u64_H(src2) && \ + u64_L(src1) < u64_L(src2)))) +#define COMPILER_64_LE(src1, src2) (u64_H(src1) < u64_H(src2) || \ + ((u64_H(src1) == u64_H(src2) && \ + u64_L(src1) <= u64_L(src2)))) +#define COMPILER_64_GT(src1, src2) (u64_H(src1) > u64_H(src2) || \ + ((u64_H(src1) == u64_H(src2) && \ + u64_L(src1) > u64_L(src2)))) +#define COMPILER_64_GE(src1, src2) (u64_H(src1) > u64_H(src2) || \ + ((u64_H(src1) == u64_H(src2) && \ + u64_L(src1) >= u64_L(src2)))) + +#endif /* !COMPILER_HAS_LONGLONG_COMPARE */ + +/* Set up a mask of width bits offset lft_shft. No error checking */ +#define COMPILER_64_MASK_CREATE(dst, width, lft_shift) \ + do { \ + COMPILER_64_ALLONES(dst); \ + COMPILER_64_SHR((dst), (64 - (width))); \ + COMPILER_64_SHL((dst), (lft_shift)); \ + } while (0) + +#define COMPILER_64_DELTA(src, last, new)\ + do { \ + COMPILER_64_ZERO(src);\ + COMPILER_64_ADD_64(src, new);\ + COMPILER_64_SUB_64(src, last);\ + } while(0) + +#define COMPILER_64_BITSET(dst, n) \ + do { \ + uint64 temp64; \ + COMPILER_64_SET(temp64, 0, 1); \ + COMPILER_64_SHL(temp64, n); \ + COMPILER_64_OR(dst, temp64); \ + } while(0) + +#define COMPILER_64_BITCLR(dst, n) \ + do { \ + uint64 temp64; \ + COMPILER_64_SET(temp64, 0, 1); \ + COMPILER_64_SHL(temp64, n); \ + COMPILER_64_NOT(temp64); \ + COMPILER_64_AND(dst, temp64); \ + } while(0) + +/** dst[dst_offset:dest_offset+nof_bits] = src[src_offset:src_offset+nof_bits] */ +#define COMPILER_64_BITCOPY_RANGE(dst, dst_offset, src, src_offset, nof_bits) \ + do { \ + uint64 temp64; \ + COMPILER_64_MASK_CREATE(temp64, nof_bits, dst_offset); \ + COMPILER_64_NOT(temp64); \ + COMPILER_64_AND(dst, temp64); \ + COMPILER_64_MASK_CREATE(temp64, nof_bits, src_offset); \ + COMPILER_64_AND(temp64, src); \ + COMPILER_64_SHR(temp64, src_offset); \ + COMPILER_64_SHL(temp64, dst_offset); \ + COMPILER_64_OR(dst, temp64); \ + } while(0) + + + /* + * 64-bit division + */ + +#if defined COMPILER_HAS_LONGLONG_DIV && ! defined (__KERNEL__) + +#define COMPILER_64_UDIV_64(dst, src) ((dst) /= (src)) + +#else /* !(defined COMPILER_HAS_LONGLONG_DIV && ! defined (__KERNEL__)) */ + +/* Divide of unsigned 64-bit and unsigned 64-bit integers, no overflow handling */ +#define COMPILER_64_UDIV_64(dst, src) \ + do { \ + uint32 q_hi = 0, q_lo = 0; \ + while( COMPILER_64_GE(dst, src) ) \ + { \ + COMPILER_64_SUB_64(dst, src); \ + if (++q_lo == 0) ++q_hi; \ + } \ + COMPILER_64_SET(dst, q_hi, q_lo); \ + } while (0) + +#endif /* defined COMPILER_HAS_LONGLONG_DIV && ! defined (__KERNEL__) */ + +#define COMPILER_64_UDIV_32(dst, src) \ + do { \ + uint64 u64_src; \ + COMPILER_64_SET(u64_src, 0, src); \ + COMPILER_64_UDIV_64(dst, u64_src); \ + } while(0) + + /* + * 64-bit power: + * dst = base^exp + */ +#define COMPILER_64_UPOW(dst, base , exp) \ + do { \ + int exp_index; \ + COMPILER_64_SET(dst, 0, 1); \ + for (exp_index = 0; exp_index < exp; exp_index++) \ + COMPILER_64_UMUL_32(dst, base); \ + } while(0) + +/* + * Some macros for double support + * + * You can use the COMPILER_DOUBLE macro + * if you would prefer double precision, but it is not necessary. + * If you need more control (or you need to print :), then + * then you should use the COMPILER_HAS_DOUBLE macro explicitly. + * + */ +#ifdef COMPILER_HAS_DOUBLE +#define COMPILER_DOUBLE double +#define COMPILER_DOUBLE_FORMAT "f" +#define COMPILER_64_TO_DOUBLE(f, i64) \ + ((f) = COMPILER_64_HI(i64) * 4294967296.0 + COMPILER_64_LO(i64)) +#define COMPILER_32_TO_DOUBLE(f, i32) \ + ((f) = (double) (i32)) +#else +#define COMPILER_DOUBLE uint32 +#define COMPILER_DOUBLE_FORMAT "u" +#define COMPILER_64_TO_DOUBLE(f, i64) ((f) = COMPILER_64_LO(i64)) +#define COMPILER_32_TO_DOUBLE(f, i32) ((f) = (i32)) +#endif + +/* + * Version of inline that is turned off for compilers that do + * not support inline. + */ + +#ifndef INLINE +# ifdef COMPILER_HAS_INLINE +# define INLINE inline +# else +# define INLINE +# endif +#endif /* !INLINE */ + +/* + * Version of const that is turned off for compilers that do + * not support const. + */ + +#ifndef CONST +# ifdef COMPILER_HAS_CONST +# define CONST const +# else +# define CONST +# endif +#endif /* !CONST */ + +/* + * Version of static that is turned off when BROADCOM_DEBUG is defined. + * Some compilers/linkers/OSs do not put static symbols in the + * symbol table, which can make debugging harder. + */ + +#ifndef STATIC +# if defined(COMPILER_HAS_STATIC) && !defined(BROADCOM_DEBUG) +# define STATIC static +# else +# define STATIC +# endif +#endif /* !STATIC */ + +#endif /* !_SAL_COMPILER_H */ diff --git a/pde-test-host/pde-test-host/include/driver_util.h b/pde-test-host/pde-test-host/include/driver_util.h new file mode 100644 index 0000000..a45ec43 --- /dev/null +++ b/pde-test-host/pde-test-host/include/driver_util.h @@ -0,0 +1,84 @@ +/********************************************************************* + * + * Copyright: (c) 2018 Broadcom. + * Broadcom Proprietary and Confidential. All rights reserved. + * + *********************************************************************/ + +#ifndef DRIVER_UTIL_H +#define DRIVER_UTIL_H + +#include + +#define LIB_DLL_EXPORTED __attribute__((__visibility__("default"))) +#define CMD_LEN_MAX 256 + +#define SAI_F_FAST_BOOT 0x00000001 /* Fast boot mode */ + +typedef struct sai_config_s +{ + char *cfg_fname; /* Configuration file name along with the path */ + unsigned int flags; /* SAI boot up flags */ + char *wb_fname; /* File to store warmboot configuration * + * along with the path */ + char *rmcfg_fname; /* RM config file name along with the path */ + char *cfg_post_fname; /* Post init configuration file name * + * along with the path */ + unsigned int sai_flags; /* SAI flags */ +} sai_init_t; + +/*****************************************************************//** +* \brief Function to initialize the switch. +* +* \param init [IN] pointer to structure that contains path to +* platform customization config file, boot flags. +* +* \return SAI_E_XXX SAI API return code +********************************************************************/ +extern int sai_driver_init(sai_init_t *init) LIB_DLL_EXPORTED ; + +/*****************************************************************//** +* \brief Function to free up the resources and exit the driver +* +* \return SAI_E_XXX SAI API return code +********************************************************************/ +extern int sai_driver_exit() LIB_DLL_EXPORTED; + +/*****************************************************************//** +* \brief Function to clear the flags necessary for warm boot support +* +* \return SAI_E_NONE SAI API return code +********************************************************************/ +int sai_warm_shut(void); + + +extern unsigned int sai_driver_boot_flags_get(void) LIB_DLL_EXPORTED; + +int driverSwitchIdGet(uint16_t *chipId, uint8_t *revision); + +#ifdef INCLUDE_DIAG_SHELL +/*****************************************************************//** +* \brief Bringup diagnostic shell prompt and process the input commands. +* +* \return SAI_E_XXX SAI API return code +********************************************************************/ +int sai_driver_shell() LIB_DLL_EXPORTED; + +/*****************************************************************//** +* \brief Process diagnostic shell command. +* +* \param commandBuf [IN] pointer to hold the diagnostic shell command +* +* \return SAI_E_XXX SAI API return code +********************************************************************/ +int sai_driver_process_command(char *commandBuf) LIB_DLL_EXPORTED; +#endif + +int driver_config_set(char *name, char *value); +int driver_process_command(int u, char *c); + +extern int driverA2BGet(int val) LIB_DLL_EXPORTED; + +extern void platform_phy_cleanup() LIB_DLL_EXPORTED; + +#endif /* DRIVER_UTIL_H */ diff --git a/pde-test-host/pde-test-host/include/hiredis/async.h b/pde-test-host/pde-test-host/include/hiredis/async.h new file mode 100644 index 0000000..268274e --- /dev/null +++ b/pde-test-host/pde-test-host/include/hiredis/async.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2009-2011, Salvatore Sanfilippo + * Copyright (c) 2010-2011, Pieter Noordhuis + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __HIREDIS_ASYNC_H +#define __HIREDIS_ASYNC_H +#include "hiredis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct redisAsyncContext; /* need forward declaration of redisAsyncContext */ +struct dict; /* dictionary header is included in async.c */ + +/* Reply callback prototype and container */ +typedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*); +typedef struct redisCallback { + struct redisCallback *next; /* simple singly linked list */ + redisCallbackFn *fn; + void *privdata; +} redisCallback; + +/* List of callbacks for either regular replies or pub/sub */ +typedef struct redisCallbackList { + redisCallback *head, *tail; +} redisCallbackList; + +/* Connection callback prototypes */ +typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status); +typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status); + +/* Context for an async connection to Redis */ +typedef struct redisAsyncContext { + /* Hold the regular context, so it can be realloc'ed. */ + redisContext c; + + /* Setup error flags so they can be used directly. */ + int err; + char *errstr; + + /* Not used by hiredis */ + void *data; + + /* Event library data and hooks */ + struct { + void *data; + + /* Hooks that are called when the library expects to start + * reading/writing. These functions should be idempotent. */ + void (*addRead)(void *privdata); + void (*delRead)(void *privdata); + void (*addWrite)(void *privdata); + void (*delWrite)(void *privdata); + void (*cleanup)(void *privdata); + } ev; + + /* Called when either the connection is terminated due to an error or per + * user request. The status is set accordingly (REDIS_OK, REDIS_ERR). */ + redisDisconnectCallback *onDisconnect; + + /* Called when the first write event was received. */ + redisConnectCallback *onConnect; + + /* Regular command callbacks */ + redisCallbackList replies; + + /* Subscription callbacks */ + struct { + redisCallbackList invalid; + struct dict *channels; + struct dict *patterns; + } sub; +} redisAsyncContext; + +/* Functions that proxy to hiredis */ +redisAsyncContext *redisAsyncConnect(const char *ip, int port); +redisAsyncContext *redisAsyncConnectUnix(const char *path); +int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn); +int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn); +void redisAsyncDisconnect(redisAsyncContext *ac); +void redisAsyncFree(redisAsyncContext *ac); + +/* Handle read/write events */ +void redisAsyncHandleRead(redisAsyncContext *ac); +void redisAsyncHandleWrite(redisAsyncContext *ac); + +/* Command functions for an async context. Write the command to the + * output buffer and register the provided callback. */ +int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap); +int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...); +int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pde-test-host/pde-test-host/include/hiredis/hiredis.h b/pde-test-host/pde-test-host/include/hiredis/hiredis.h new file mode 100644 index 0000000..a743760 --- /dev/null +++ b/pde-test-host/pde-test-host/include/hiredis/hiredis.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2009-2011, Salvatore Sanfilippo + * Copyright (c) 2010-2014, Pieter Noordhuis + * Copyright (c) 2015, Matt Stancliff , + * Jan-Erik Rediger + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __HIREDIS_H +#define __HIREDIS_H +#include "read.h" +#include /* for va_list */ +#include /* for struct timeval */ +#include /* uintXX_t, etc */ +#include "sds.h" /* for sds */ + +#define HIREDIS_MAJOR 0 +#define HIREDIS_MINOR 13 +#define HIREDIS_PATCH 3 +#define HIREDIS_SONAME 0.13 + +/* Connection type can be blocking or non-blocking and is set in the + * least significant bit of the flags field in redisContext. */ +#define REDIS_BLOCK 0x1 + +/* Connection may be disconnected before being free'd. The second bit + * in the flags field is set when the context is connected. */ +#define REDIS_CONNECTED 0x2 + +/* The async API might try to disconnect cleanly and flush the output + * buffer and read all subsequent replies before disconnecting. + * This flag means no new commands can come in and the connection + * should be terminated once all replies have been read. */ +#define REDIS_DISCONNECTING 0x4 + +/* Flag specific to the async API which means that the context should be clean + * up as soon as possible. */ +#define REDIS_FREEING 0x8 + +/* Flag that is set when an async callback is executed. */ +#define REDIS_IN_CALLBACK 0x10 + +/* Flag that is set when the async context has one or more subscriptions. */ +#define REDIS_SUBSCRIBED 0x20 + +/* Flag that is set when monitor mode is active */ +#define REDIS_MONITORING 0x40 + +/* Flag that is set when we should set SO_REUSEADDR before calling bind() */ +#define REDIS_REUSEADDR 0x80 + +#define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */ + +/* number of times we retry to connect in the case of EADDRNOTAVAIL and + * SO_REUSEADDR is being used. */ +#define REDIS_CONNECT_RETRIES 10 + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is the reply object returned by redisCommand() */ +typedef struct redisReply { + int type; /* REDIS_REPLY_* */ + long long integer; /* The integer when type is REDIS_REPLY_INTEGER */ + size_t len; /* Length of string */ + char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */ + size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */ + struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */ +} redisReply; + +redisReader *redisReaderCreate(void); + +/* Function to free the reply objects hiredis returns by default. */ +void freeReplyObject(void *reply); + +/* Functions to format a command according to the protocol. */ +int redisvFormatCommand(char **target, const char *format, va_list ap); +int redisFormatCommand(char **target, const char *format, ...); +int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen); +int redisFormatSdsCommandArgv(sds *target, int argc, const char ** argv, const size_t *argvlen); +void redisFreeCommand(char *cmd); +void redisFreeSdsCommand(sds cmd); + +enum redisConnectionType { + REDIS_CONN_TCP, + REDIS_CONN_UNIX +}; + +/* Context for a connection to Redis */ +typedef struct redisContext { + int err; /* Error flags, 0 when there is no error */ + char errstr[128]; /* String representation of error when applicable */ + int fd; + int flags; + char *obuf; /* Write buffer */ + redisReader *reader; /* Protocol reader */ + + enum redisConnectionType connection_type; + struct timeval *timeout; + + struct { + char *host; + char *source_addr; + int port; + } tcp; + + struct { + char *path; + } unix_sock; + +} redisContext; + +redisContext *redisConnect(const char *ip, int port); +redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv); +redisContext *redisConnectNonBlock(const char *ip, int port); +redisContext *redisConnectBindNonBlock(const char *ip, int port, + const char *source_addr); +redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port, + const char *source_addr); +redisContext *redisConnectUnix(const char *path); +redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv); +redisContext *redisConnectUnixNonBlock(const char *path); +redisContext *redisConnectFd(int fd); + +/** + * Reconnect the given context using the saved information. + * + * This re-uses the exact same connect options as in the initial connection. + * host, ip (or path), timeout and bind address are reused, + * flags are used unmodified from the existing context. + * + * Returns REDIS_OK on successful connect or REDIS_ERR otherwise. + */ +int redisReconnect(redisContext *c); + +int redisSetTimeout(redisContext *c, const struct timeval tv); +int redisEnableKeepAlive(redisContext *c); +void redisFree(redisContext *c); +int redisFreeKeepFd(redisContext *c); +int redisBufferRead(redisContext *c); +int redisBufferWrite(redisContext *c, int *done); + +/* In a blocking context, this function first checks if there are unconsumed + * replies to return and returns one if so. Otherwise, it flushes the output + * buffer to the socket and reads until it has a reply. In a non-blocking + * context, it will return unconsumed replies until there are no more. */ +int redisGetReply(redisContext *c, void **reply); +int redisGetReplyFromReader(redisContext *c, void **reply); + +/* Write a formatted command to the output buffer. Use these functions in blocking mode + * to get a pipeline of commands. */ +int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len); + +/* Write a command to the output buffer. Use these functions in blocking mode + * to get a pipeline of commands. */ +int redisvAppendCommand(redisContext *c, const char *format, va_list ap); +int redisAppendCommand(redisContext *c, const char *format, ...); +int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); + +/* Issue a command to Redis. In a blocking context, it is identical to calling + * redisAppendCommand, followed by redisGetReply. The function will return + * NULL if there was an error in performing the request, otherwise it will + * return the reply. In a non-blocking context, it is identical to calling + * only redisAppendCommand and will always return NULL. */ +void *redisvCommand(redisContext *c, const char *format, va_list ap); +void *redisCommand(redisContext *c, const char *format, ...); +void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pde-test-host/pde-test-host/include/hiredis/read.h b/pde-test-host/pde-test-host/include/hiredis/read.h new file mode 100644 index 0000000..2988aa4 --- /dev/null +++ b/pde-test-host/pde-test-host/include/hiredis/read.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2009-2011, Salvatore Sanfilippo + * Copyright (c) 2010-2011, Pieter Noordhuis + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef __HIREDIS_READ_H +#define __HIREDIS_READ_H +#include /* for size_t */ + +#define REDIS_ERR -1 +#define REDIS_OK 0 + +/* When an error occurs, the err flag in a context is set to hold the type of + * error that occurred. REDIS_ERR_IO means there was an I/O error and you + * should use the "errno" variable to find out what is wrong. + * For other values, the "errstr" field will hold a description. */ +#define REDIS_ERR_IO 1 /* Error in read or write */ +#define REDIS_ERR_EOF 3 /* End of file */ +#define REDIS_ERR_PROTOCOL 4 /* Protocol error */ +#define REDIS_ERR_OOM 5 /* Out of memory */ +#define REDIS_ERR_OTHER 2 /* Everything else... */ + +#define REDIS_REPLY_STRING 1 +#define REDIS_REPLY_ARRAY 2 +#define REDIS_REPLY_INTEGER 3 +#define REDIS_REPLY_NIL 4 +#define REDIS_REPLY_STATUS 5 +#define REDIS_REPLY_ERROR 6 + +#define REDIS_READER_MAX_BUF (1024*16) /* Default max unused reader buffer. */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct redisReadTask { + int type; + int elements; /* number of elements in multibulk container */ + int idx; /* index in parent (array) object */ + void *obj; /* holds user-generated value for a read task */ + struct redisReadTask *parent; /* parent task */ + void *privdata; /* user-settable arbitrary field */ +} redisReadTask; + +typedef struct redisReplyObjectFunctions { + void *(*createString)(const redisReadTask*, char*, size_t); + void *(*createArray)(const redisReadTask*, int); + void *(*createInteger)(const redisReadTask*, long long); + void *(*createNil)(const redisReadTask*); + void (*freeObject)(void*); +} redisReplyObjectFunctions; + +typedef struct redisReader { + int err; /* Error flags, 0 when there is no error */ + char errstr[128]; /* String representation of error when applicable */ + + char *buf; /* Read buffer */ + size_t pos; /* Buffer cursor */ + size_t len; /* Buffer length */ + size_t maxbuf; /* Max length of unused buffer */ + + redisReadTask rstack[9]; + int ridx; /* Index of current read task */ + void *reply; /* Temporary reply pointer */ + + redisReplyObjectFunctions *fn; + void *privdata; +} redisReader; + +/* Public API for the protocol parser. */ +redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn); +void redisReaderFree(redisReader *r); +int redisReaderFeed(redisReader *r, const char *buf, size_t len); +int redisReaderGetReply(redisReader *r, void **reply); + +#define redisReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p)) +#define redisReaderGetObject(_r) (((redisReader*)(_r))->reply) +#define redisReaderGetError(_r) (((redisReader*)(_r))->errstr) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pde-test-host/pde-test-host/include/hiredis/sds.h b/pde-test-host/pde-test-host/include/hiredis/sds.h new file mode 100644 index 0000000..13be75a --- /dev/null +++ b/pde-test-host/pde-test-host/include/hiredis/sds.h @@ -0,0 +1,273 @@ +/* SDSLib 2.0 -- A C dynamic strings library + * + * Copyright (c) 2006-2015, Salvatore Sanfilippo + * Copyright (c) 2015, Oran Agra + * Copyright (c) 2015, Redis Labs, Inc + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SDS_H +#define __SDS_H + +#define SDS_MAX_PREALLOC (1024*1024) + +#include +#include +#include + +typedef char *sds; + +/* Note: sdshdr5 is never used, we just access the flags byte directly. + * However is here to document the layout of type 5 SDS strings. */ +struct __attribute__ ((__packed__)) sdshdr5 { + unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ + char buf[]; +}; +struct __attribute__ ((__packed__)) sdshdr8 { + uint8_t len; /* used */ + uint8_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; +}; +struct __attribute__ ((__packed__)) sdshdr16 { + uint16_t len; /* used */ + uint16_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; +}; +struct __attribute__ ((__packed__)) sdshdr32 { + uint32_t len; /* used */ + uint32_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; +}; +struct __attribute__ ((__packed__)) sdshdr64 { + uint64_t len; /* used */ + uint64_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; +}; + +#define SDS_TYPE_5 0 +#define SDS_TYPE_8 1 +#define SDS_TYPE_16 2 +#define SDS_TYPE_32 3 +#define SDS_TYPE_64 4 +#define SDS_TYPE_MASK 7 +#define SDS_TYPE_BITS 3 +#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))); +#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T)))) +#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS) + +static inline size_t sdslen(const sds s) { + unsigned char flags = s[-1]; + switch(flags&SDS_TYPE_MASK) { + case SDS_TYPE_5: + return SDS_TYPE_5_LEN(flags); + case SDS_TYPE_8: + return SDS_HDR(8,s)->len; + case SDS_TYPE_16: + return SDS_HDR(16,s)->len; + case SDS_TYPE_32: + return SDS_HDR(32,s)->len; + case SDS_TYPE_64: + return SDS_HDR(64,s)->len; + } + return 0; +} + +static inline size_t sdsavail(const sds s) { + unsigned char flags = s[-1]; + switch(flags&SDS_TYPE_MASK) { + case SDS_TYPE_5: { + return 0; + } + case SDS_TYPE_8: { + SDS_HDR_VAR(8,s); + return sh->alloc - sh->len; + } + case SDS_TYPE_16: { + SDS_HDR_VAR(16,s); + return sh->alloc - sh->len; + } + case SDS_TYPE_32: { + SDS_HDR_VAR(32,s); + return sh->alloc - sh->len; + } + case SDS_TYPE_64: { + SDS_HDR_VAR(64,s); + return sh->alloc - sh->len; + } + } + return 0; +} + +static inline void sdssetlen(sds s, size_t newlen) { + unsigned char flags = s[-1]; + switch(flags&SDS_TYPE_MASK) { + case SDS_TYPE_5: + { + unsigned char *fp = ((unsigned char*)s)-1; + *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); + } + break; + case SDS_TYPE_8: + SDS_HDR(8,s)->len = newlen; + break; + case SDS_TYPE_16: + SDS_HDR(16,s)->len = newlen; + break; + case SDS_TYPE_32: + SDS_HDR(32,s)->len = newlen; + break; + case SDS_TYPE_64: + SDS_HDR(64,s)->len = newlen; + break; + } +} + +static inline void sdsinclen(sds s, size_t inc) { + unsigned char flags = s[-1]; + switch(flags&SDS_TYPE_MASK) { + case SDS_TYPE_5: + { + unsigned char *fp = ((unsigned char*)s)-1; + unsigned char newlen = SDS_TYPE_5_LEN(flags)+inc; + *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); + } + break; + case SDS_TYPE_8: + SDS_HDR(8,s)->len += inc; + break; + case SDS_TYPE_16: + SDS_HDR(16,s)->len += inc; + break; + case SDS_TYPE_32: + SDS_HDR(32,s)->len += inc; + break; + case SDS_TYPE_64: + SDS_HDR(64,s)->len += inc; + break; + } +} + +/* sdsalloc() = sdsavail() + sdslen() */ +static inline size_t sdsalloc(const sds s) { + unsigned char flags = s[-1]; + switch(flags&SDS_TYPE_MASK) { + case SDS_TYPE_5: + return SDS_TYPE_5_LEN(flags); + case SDS_TYPE_8: + return SDS_HDR(8,s)->alloc; + case SDS_TYPE_16: + return SDS_HDR(16,s)->alloc; + case SDS_TYPE_32: + return SDS_HDR(32,s)->alloc; + case SDS_TYPE_64: + return SDS_HDR(64,s)->alloc; + } + return 0; +} + +static inline void sdssetalloc(sds s, size_t newlen) { + unsigned char flags = s[-1]; + switch(flags&SDS_TYPE_MASK) { + case SDS_TYPE_5: + /* Nothing to do, this type has no total allocation info. */ + break; + case SDS_TYPE_8: + SDS_HDR(8,s)->alloc = newlen; + break; + case SDS_TYPE_16: + SDS_HDR(16,s)->alloc = newlen; + break; + case SDS_TYPE_32: + SDS_HDR(32,s)->alloc = newlen; + break; + case SDS_TYPE_64: + SDS_HDR(64,s)->alloc = newlen; + break; + } +} + +sds sdsnewlen(const void *init, size_t initlen); +sds sdsnew(const char *init); +sds sdsempty(void); +sds sdsdup(const sds s); +void sdsfree(sds s); +sds sdsgrowzero(sds s, size_t len); +sds sdscatlen(sds s, const void *t, size_t len); +sds sdscat(sds s, const char *t); +sds sdscatsds(sds s, const sds t); +sds sdscpylen(sds s, const char *t, size_t len); +sds sdscpy(sds s, const char *t); + +sds sdscatvprintf(sds s, const char *fmt, va_list ap); +#ifdef __GNUC__ +sds sdscatprintf(sds s, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); +#else +sds sdscatprintf(sds s, const char *fmt, ...); +#endif + +sds sdscatfmt(sds s, char const *fmt, ...); +sds sdstrim(sds s, const char *cset); +void sdsrange(sds s, int start, int end); +void sdsupdatelen(sds s); +void sdsclear(sds s); +int sdscmp(const sds s1, const sds s2); +sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count); +void sdsfreesplitres(sds *tokens, int count); +void sdstolower(sds s); +void sdstoupper(sds s); +sds sdsfromlonglong(long long value); +sds sdscatrepr(sds s, const char *p, size_t len); +sds *sdssplitargs(const char *line, int *argc); +sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen); +sds sdsjoin(char **argv, int argc, char *sep); +sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen); + +/* Low level functions exposed to the user API */ +sds sdsMakeRoomFor(sds s, size_t addlen); +void sdsIncrLen(sds s, int incr); +sds sdsRemoveFreeSpace(sds s); +size_t sdsAllocSize(sds s); +void *sdsAllocPtr(sds s); + +/* Export the allocator used by SDS to the program using SDS. + * Sometimes the program SDS is linked to, may use a different set of + * allocators, but may want to allocate or free things that SDS will + * respectively free or allocate. */ +void *sds_malloc(size_t size); +void *sds_realloc(void *ptr, size_t size); +void sds_free(void *ptr); + +#ifdef REDIS_TEST +int sdsTest(int argc, char *argv[]); +#endif + +#endif diff --git a/pde-test-host/pde-test-host/include/pcap/bpf.h b/pde-test-host/pde-test-host/include/pcap/bpf.h new file mode 100644 index 0000000..ad36eb6 --- /dev/null +++ b/pde-test-host/pde-test-host/include/pcap/bpf.h @@ -0,0 +1,1338 @@ +/*- + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bpf.h 7.1 (Berkeley) 5/7/91 + * + * @(#) $Header: /tcpdump/master/libpcap/pcap/bpf.h,v 1.32 2008-12-23 20:13:29 guy Exp $ (LBL) + */ + +/* + * This is libpcap's cut-down version of bpf.h; it includes only + * the stuff needed for the code generator and the userland BPF + * interpreter, and the libpcap APIs for setting filters, etc.. + * + * "pcap-bpf.c" will include the native OS version, as it deals with + * the OS's BPF implementation. + * + * At least two programs found by Google Code Search explicitly includes + * (even though / includes it for you), + * so moving that stuff to would break the build for some + * programs. + */ + +/* + * If we've already included , don't re-define this stuff. + * We assume BSD-style multiple-include protection in , + * which is true of all but the oldest versions of FreeBSD and NetBSD, + * or Tru64 UNIX-style multiple-include protection (or, at least, + * Tru64 UNIX 5.x-style; I don't have earlier versions available to check), + * or AIX-style multiple-include protection (or, at least, AIX 5.x-style; + * I don't have earlier versions available to check). + * + * We do not check for BPF_MAJOR_VERSION, as that's defined by + * , which is directly or indirectly included in some + * programs that also include pcap.h, and doesn't + * define stuff we need. + * + * This also provides our own multiple-include protection. + */ +#if !defined(_NET_BPF_H_) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h) +#define lib_pcap_bpf_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* BSD style release date */ +#define BPF_RELEASE 199606 + +#ifdef MSDOS /* must be 32-bit */ +typedef long bpf_int32; +typedef unsigned long bpf_u_int32; +#else +typedef int bpf_int32; +typedef u_int bpf_u_int32; +#endif + +/* + * Alignment macros. BPF_WORDALIGN rounds up to the next + * even multiple of BPF_ALIGNMENT. + * + * Tcpdump's print-pflog.c uses this, so we define it here. + */ +#ifndef __NetBSD__ +#define BPF_ALIGNMENT sizeof(bpf_int32) +#else +#define BPF_ALIGNMENT sizeof(long) +#endif +#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1)) + +/* + * Structure for "pcap_compile()", "pcap_setfilter()", etc.. + */ +struct bpf_program { + u_int bf_len; + struct bpf_insn *bf_insns; +}; + +/* + * Link-layer header type codes. + * + * Do *NOT* add new values to this list without asking + * "tcpdump-workers@lists.tcpdump.org" for a value. Otherwise, you run + * the risk of using a value that's already being used for some other + * purpose, and of having tools that read libpcap-format captures not + * being able to handle captures with your new DLT_ value, with no hope + * that they will ever be changed to do so (as that would destroy their + * ability to read captures using that value for that other purpose). + * + * See + * + * http://www.tcpdump.org/linktypes.html + * + * for detailed descriptions of some of these link-layer header types. + */ + +/* + * These are the types that are the same on all platforms, and that + * have been defined by for ages. + */ +#define DLT_NULL 0 /* BSD loopback encapsulation */ +#define DLT_EN10MB 1 /* Ethernet (10Mb) */ +#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ +#define DLT_AX25 3 /* Amateur Radio AX.25 */ +#define DLT_PRONET 4 /* Proteon ProNET Token Ring */ +#define DLT_CHAOS 5 /* Chaos */ +#define DLT_IEEE802 6 /* 802.5 Token Ring */ +#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */ +#define DLT_SLIP 8 /* Serial Line IP */ +#define DLT_PPP 9 /* Point-to-point Protocol */ +#define DLT_FDDI 10 /* FDDI */ + +/* + * These are types that are different on some platforms, and that + * have been defined by for ages. We use #ifdefs to + * detect the BSDs that define them differently from the traditional + * libpcap + * + * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS, + * but I don't know what the right #define is for BSD/OS. + */ +#define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */ + +#ifdef __OpenBSD__ +#define DLT_RAW 14 /* raw IP */ +#else +#define DLT_RAW 12 /* raw IP */ +#endif + +/* + * Given that the only OS that currently generates BSD/OS SLIP or PPP + * is, well, BSD/OS, arguably everybody should have chosen its values + * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they + * didn't. So it goes. + */ +#if defined(__NetBSD__) || defined(__FreeBSD__) +#ifndef DLT_SLIP_BSDOS +#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */ +#endif +#else +#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ +#endif + +/* + * 17 was used for DLT_PFLOG in OpenBSD; it no longer is. + * + * It was DLT_LANE8023 in SuSE 6.3, so we defined LINKTYPE_PFLOG + * as 117 so that pflog captures would use a link-layer header type + * value that didn't collide with any other values. On all + * platforms other than OpenBSD, we defined DLT_PFLOG as 117, + * and we mapped between LINKTYPE_PFLOG and DLT_PFLOG. + * + * OpenBSD eventually switched to using 117 for DLT_PFLOG as well. + * + * Don't use 17 for anything else. + */ + +/* + * 18 is used for DLT_PFSYNC in OpenBSD, NetBSD, DragonFly BSD and + * Mac OS X; don't use it for anything else. (FreeBSD uses 121, + * which collides with DLT_HHDLC, even though it doesn't use 18 + * for anything and doesn't appear to have ever used it for anything.) + * + * We define it as 18 on those platforms; it is, unfortunately, used + * for DLT_CIP in Suse 6.3, so we don't define it as DLT_PFSYNC + * in general. As the packet format for it, like that for + * DLT_PFLOG, is not only OS-dependent but OS-version-dependent, + * we don't support printing it in tcpdump except on OSes that + * have the relevant header files, so it's not that useful on + * other platforms. + */ +#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__) +#define DLT_PFSYNC 18 +#endif + +#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ + +/* + * Apparently Redback uses this for its SmartEdge 400/800. I hope + * nobody else decided to use it, too. + */ +#define DLT_REDBACK_SMARTEDGE 32 + +/* + * These values are defined by NetBSD; other platforms should refrain from + * using them for other purposes, so that NetBSD savefiles with link + * types of 50 or 51 can be read as this type on all platforms. + */ +#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ +#define DLT_PPP_ETHER 51 /* PPP over Ethernet */ + +/* + * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses + * a link-layer type of 99 for the tcpdump it supplies. The link-layer + * header has 6 bytes of unknown data, something that appears to be an + * Ethernet type, and 36 bytes that appear to be 0 in at least one capture + * I've seen. + */ +#define DLT_SYMANTEC_FIREWALL 99 + +/* + * Values between 100 and 103 are used in capture file headers as + * link-layer header type LINKTYPE_ values corresponding to DLT_ types + * that differ between platforms; don't use those values for new DLT_ + * new types. + */ + +/* + * Values starting with 104 are used for newly-assigned link-layer + * header type values; for those link-layer header types, the DLT_ + * value returned by pcap_datalink() and passed to pcap_open_dead(), + * and the LINKTYPE_ value that appears in capture files, are the + * same. + * + * DLT_MATCHING_MIN is the lowest such value; DLT_MATCHING_MAX is + * the highest such value. + */ +#define DLT_MATCHING_MIN 104 + +/* + * This value was defined by libpcap 0.5; platforms that have defined + * it with a different value should define it here with that value - + * a link type of 104 in a save file will be mapped to DLT_C_HDLC, + * whatever value that happens to be, so programs will correctly + * handle files with that link type regardless of the value of + * DLT_C_HDLC. + * + * The name DLT_C_HDLC was used by BSD/OS; we use that name for source + * compatibility with programs written for BSD/OS. + * + * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well, + * for source compatibility with programs written for libpcap 0.5. + */ +#define DLT_C_HDLC 104 /* Cisco HDLC */ +#define DLT_CHDLC DLT_C_HDLC + +#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ + +/* + * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW, + * except when it isn't. (I.e., sometimes it's just raw IP, and + * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL, + * so that we don't have to worry about the link-layer header.) + */ + +/* + * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides + * with other values. + * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header + * (DLCI, etc.). + */ +#define DLT_FRELAY 107 + +/* + * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except + * that the AF_ type in the link-layer header is in network byte order. + * + * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so + * we don't use 12 for it in OSes other than OpenBSD. + */ +#ifdef __OpenBSD__ +#define DLT_LOOP 12 +#else +#define DLT_LOOP 108 +#endif + +/* + * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's + * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other + * than OpenBSD. + */ +#ifdef __OpenBSD__ +#define DLT_ENC 13 +#else +#define DLT_ENC 109 +#endif + +/* + * Values between 110 and 112 are reserved for use in capture file headers + * as link-layer types corresponding to DLT_ types that might differ + * between platforms; don't use those values for new DLT_ types + * other than the corresponding DLT_ types. + */ + +/* + * This is for Linux cooked sockets. + */ +#define DLT_LINUX_SLL 113 + +/* + * Apple LocalTalk hardware. + */ +#define DLT_LTALK 114 + +/* + * Acorn Econet. + */ +#define DLT_ECONET 115 + +/* + * Reserved for use with OpenBSD ipfilter. + */ +#define DLT_IPFILTER 116 + +/* + * OpenBSD DLT_PFLOG. + */ +#define DLT_PFLOG 117 + +/* + * Registered for Cisco-internal use. + */ +#define DLT_CISCO_IOS 118 + +/* + * For 802.11 cards using the Prism II chips, with a link-layer + * header including Prism monitor mode information plus an 802.11 + * header. + */ +#define DLT_PRISM_HEADER 119 + +/* + * Reserved for Aironet 802.11 cards, with an Aironet link-layer header + * (see Doug Ambrisko's FreeBSD patches). + */ +#define DLT_AIRONET_HEADER 120 + +/* + * Sigh. + * + * This was reserved for Siemens HiPath HDLC on 2002-01-25, as + * requested by Tomas Kukosa. + * + * On 2004-02-25, a FreeBSD checkin to sys/net/bpf.h was made that + * assigned 121 as DLT_PFSYNC. Its libpcap does DLT_ <-> LINKTYPE_ + * mapping, so it probably supports capturing on the pfsync device + * but not saving the captured data to a pcap file. + * + * OpenBSD, from which pf came, however, uses 18 for DLT_PFSYNC; + * their libpcap does no DLT_ <-> LINKTYPE_ mapping, so it would + * use 18 in pcap files as well. + * + * NetBSD and DragonFly BSD also use 18 for DLT_PFSYNC; their + * libpcaps do DLT_ <-> LINKTYPE_ mapping, and neither has an entry + * for DLT_PFSYNC, so it might not be able to write out dump files + * with 18 as the link-layer header type. (Earlier versions might + * not have done mapping, in which case they'd work the same way + * OpenBSD does.) + * + * Mac OS X defines it as 18, but doesn't appear to use it as of + * Mac OS X 10.7.3. Its libpcap does DLT_ <-> LINKTYPE_ mapping. + * + * We'll define DLT_PFSYNC as 121 on FreeBSD and define it as 18 on + * all other platforms. We'll define DLT_HHDLC as 121 on everything + * except for FreeBSD; anybody who wants to compile, on FreeBSD, code + * that uses DLT_HHDLC is out of luck. + * + * We'll define LINKTYPE_PFSYNC as 18, *even on FreeBSD*, and map + * it, so that savefiles won't use 121 for PFSYNC - they'll all + * use 18. Code that uses pcap_datalink() to determine the link-layer + * header type of a savefile won't, when built and run on FreeBSD, + * be able to distinguish between LINKTYPE_PFSYNC and LINKTYPE_HHDLC + * capture files; code that doesn't, such as the code in Wireshark, + * will be able to distinguish between them. + */ +#ifdef __FreeBSD__ +#define DLT_PFSYNC 121 +#else +#define DLT_HHDLC 121 +#endif + +/* + * This is for RFC 2625 IP-over-Fibre Channel. + * + * This is not for use with raw Fibre Channel, where the link-layer + * header starts with a Fibre Channel frame header; it's for IP-over-FC, + * where the link-layer header starts with an RFC 2625 Network_Header + * field. + */ +#define DLT_IP_OVER_FC 122 + +/* + * This is for Full Frontal ATM on Solaris with SunATM, with a + * pseudo-header followed by an AALn PDU. + * + * There may be other forms of Full Frontal ATM on other OSes, + * with different pseudo-headers. + * + * If ATM software returns a pseudo-header with VPI/VCI information + * (and, ideally, packet type information, e.g. signalling, ILMI, + * LANE, LLC-multiplexed traffic, etc.), it should not use + * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump + * and the like don't have to infer the presence or absence of a + * pseudo-header and the form of the pseudo-header. + */ +#define DLT_SUNATM 123 /* Solaris+SunATM */ + +/* + * Reserved as per request from Kent Dahlgren + * for private use. + */ +#define DLT_RIO 124 /* RapidIO */ +#define DLT_PCI_EXP 125 /* PCI Express */ +#define DLT_AURORA 126 /* Xilinx Aurora link layer */ + +/* + * Header for 802.11 plus a number of bits of link-layer information + * including radio information, used by some recent BSD drivers as + * well as the madwifi Atheros driver for Linux. + */ +#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */ + +/* + * Reserved for the TZSP encapsulation, as per request from + * Chris Waters + * TZSP is a generic encapsulation for any other link type, + * which includes a means to include meta-information + * with the packet, e.g. signal strength and channel + * for 802.11 packets. + */ +#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */ + +/* + * BSD's ARCNET headers have the source host, destination host, + * and type at the beginning of the packet; that's what's handed + * up to userland via BPF. + * + * Linux's ARCNET headers, however, have a 2-byte offset field + * between the host IDs and the type; that's what's handed up + * to userland via PF_PACKET sockets. + * + * We therefore have to have separate DLT_ values for them. + */ +#define DLT_ARCNET_LINUX 129 /* ARCNET */ + +/* + * Juniper-private data link types, as per request from + * Hannes Gredler . The DLT_s are used + * for passing on chassis-internal metainformation such as + * QOS profiles, etc.. + */ +#define DLT_JUNIPER_MLPPP 130 +#define DLT_JUNIPER_MLFR 131 +#define DLT_JUNIPER_ES 132 +#define DLT_JUNIPER_GGSN 133 +#define DLT_JUNIPER_MFR 134 +#define DLT_JUNIPER_ATM2 135 +#define DLT_JUNIPER_SERVICES 136 +#define DLT_JUNIPER_ATM1 137 + +/* + * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund + * . The header that's presented is an Ethernet-like + * header: + * + * #define FIREWIRE_EUI64_LEN 8 + * struct firewire_header { + * u_char firewire_dhost[FIREWIRE_EUI64_LEN]; + * u_char firewire_shost[FIREWIRE_EUI64_LEN]; + * u_short firewire_type; + * }; + * + * with "firewire_type" being an Ethernet type value, rather than, + * for example, raw GASP frames being handed up. + */ +#define DLT_APPLE_IP_OVER_IEEE1394 138 + +/* + * Various SS7 encapsulations, as per a request from Jeff Morriss + * and subsequent discussions. + */ +#define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */ +#define DLT_MTP2 140 /* MTP2, without pseudo-header */ +#define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */ +#define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */ + +/* + * DOCSIS MAC frames. + */ +#define DLT_DOCSIS 143 + +/* + * Linux-IrDA packets. Protocol defined at http://www.irda.org. + * Those packets include IrLAP headers and above (IrLMP...), but + * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy + * framing can be handled by the hardware and depend on the bitrate. + * This is exactly the format you would get capturing on a Linux-IrDA + * interface (irdaX), but not on a raw serial port. + * Note the capture is done in "Linux-cooked" mode, so each packet include + * a fake packet header (struct sll_header). This is because IrDA packet + * decoding is dependant on the direction of the packet (incomming or + * outgoing). + * When/if other platform implement IrDA capture, we may revisit the + * issue and define a real DLT_IRDA... + * Jean II + */ +#define DLT_LINUX_IRDA 144 + +/* + * Reserved for IBM SP switch and IBM Next Federation switch. + */ +#define DLT_IBM_SP 145 +#define DLT_IBM_SN 146 + +/* + * Reserved for private use. If you have some link-layer header type + * that you want to use within your organization, with the capture files + * using that link-layer header type not ever be sent outside your + * organization, you can use these values. + * + * No libpcap release will use these for any purpose, nor will any + * tcpdump release use them, either. + * + * Do *NOT* use these in capture files that you expect anybody not using + * your private versions of capture-file-reading tools to read; in + * particular, do *NOT* use them in products, otherwise you may find that + * people won't be able to use tcpdump, or snort, or Ethereal, or... to + * read capture files from your firewall/intrusion detection/traffic + * monitoring/etc. appliance, or whatever product uses that DLT_ value, + * and you may also find that the developers of those applications will + * not accept patches to let them read those files. + * + * Also, do not use them if somebody might send you a capture using them + * for *their* private type and tools using them for *your* private type + * would have to read them. + * + * Instead, ask "tcpdump-workers@lists.tcpdump.org" for a new DLT_ value, + * as per the comment above, and use the type you're given. + */ +#define DLT_USER0 147 +#define DLT_USER1 148 +#define DLT_USER2 149 +#define DLT_USER3 150 +#define DLT_USER4 151 +#define DLT_USER5 152 +#define DLT_USER6 153 +#define DLT_USER7 154 +#define DLT_USER8 155 +#define DLT_USER9 156 +#define DLT_USER10 157 +#define DLT_USER11 158 +#define DLT_USER12 159 +#define DLT_USER13 160 +#define DLT_USER14 161 +#define DLT_USER15 162 + +/* + * For future use with 802.11 captures - defined by AbsoluteValue + * Systems to store a number of bits of link-layer information + * including radio information: + * + * http://www.shaftnet.org/~pizza/software/capturefrm.txt + * + * but it might be used by some non-AVS drivers now or in the + * future. + */ +#define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */ + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . The DLT_s are used + * for passing on chassis-internal metainformation such as + * QOS profiles, etc.. + */ +#define DLT_JUNIPER_MONITOR 164 + +/* + * BACnet MS/TP frames. + */ +#define DLT_BACNET_MS_TP 165 + +/* + * Another PPP variant as per request from Karsten Keil . + * + * This is used in some OSes to allow a kernel socket filter to distinguish + * between incoming and outgoing packets, on a socket intended to + * supply pppd with outgoing packets so it can do dial-on-demand and + * hangup-on-lack-of-demand; incoming packets are filtered out so they + * don't cause pppd to hold the connection up (you don't want random + * input packets such as port scans, packets from old lost connections, + * etc. to force the connection to stay up). + * + * The first byte of the PPP header (0xff03) is modified to accomodate + * the direction - 0x00 = IN, 0x01 = OUT. + */ +#define DLT_PPP_PPPD 166 + +/* + * Names for backwards compatibility with older versions of some PPP + * software; new software should use DLT_PPP_PPPD. + */ +#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD +#define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . The DLT_s are used + * for passing on chassis-internal metainformation such as + * QOS profiles, cookies, etc.. + */ +#define DLT_JUNIPER_PPPOE 167 +#define DLT_JUNIPER_PPPOE_ATM 168 + +#define DLT_GPRS_LLC 169 /* GPRS LLC */ +#define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */ +#define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */ + +/* + * Requested by Oolan Zimmer for use in Gcom's T1/E1 line + * monitoring equipment. + */ +#define DLT_GCOM_T1E1 172 +#define DLT_GCOM_SERIAL 173 + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . The DLT_ is used + * for internal communication to Physical Interface Cards (PIC) + */ +#define DLT_JUNIPER_PIC_PEER 174 + +/* + * Link types requested by Gregor Maier of Endace + * Measurement Systems. They add an ERF header (see + * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of + * the link-layer header. + */ +#define DLT_ERF_ETH 175 /* Ethernet */ +#define DLT_ERF_POS 176 /* Packet-over-SONET */ + +/* + * Requested by Daniele Orlandi for raw LAPD + * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header + * includes additional information before the LAPD header, so it's + * not necessarily a generic LAPD header. + */ +#define DLT_LINUX_LAPD 177 + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . + * The DLT_ are used for prepending meta-information + * like interface index, interface name + * before standard Ethernet, PPP, Frelay & C-HDLC Frames + */ +#define DLT_JUNIPER_ETHER 178 +#define DLT_JUNIPER_PPP 179 +#define DLT_JUNIPER_FRELAY 180 +#define DLT_JUNIPER_CHDLC 181 + +/* + * Multi Link Frame Relay (FRF.16) + */ +#define DLT_MFR 182 + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . + * The DLT_ is used for internal communication with a + * voice Adapter Card (PIC) + */ +#define DLT_JUNIPER_VP 183 + +/* + * Arinc 429 frames. + * DLT_ requested by Gianluca Varenni . + * Every frame contains a 32bit A429 label. + * More documentation on Arinc 429 can be found at + * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf + */ +#define DLT_A429 184 + +/* + * Arinc 653 Interpartition Communication messages. + * DLT_ requested by Gianluca Varenni . + * Please refer to the A653-1 standard for more information. + */ +#define DLT_A653_ICM 185 + +/* + * USB packets, beginning with a USB setup header; requested by + * Paolo Abeni . + */ +#define DLT_USB 186 + +/* + * Bluetooth HCI UART transport layer (part H:4); requested by + * Paolo Abeni. + */ +#define DLT_BLUETOOTH_HCI_H4 187 + +/* + * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz + * . + */ +#define DLT_IEEE802_16_MAC_CPS 188 + +/* + * USB packets, beginning with a Linux USB header; requested by + * Paolo Abeni . + */ +#define DLT_USB_LINUX 189 + +/* + * Controller Area Network (CAN) v. 2.0B packets. + * DLT_ requested by Gianluca Varenni . + * Used to dump CAN packets coming from a CAN Vector board. + * More documentation on the CAN v2.0B frames can be found at + * http://www.can-cia.org/downloads/?269 + */ +#define DLT_CAN20B 190 + +/* + * IEEE 802.15.4, with address fields padded, as is done by Linux + * drivers; requested by Juergen Schimmer. + */ +#define DLT_IEEE802_15_4_LINUX 191 + +/* + * Per Packet Information encapsulated packets. + * DLT_ requested by Gianluca Varenni . + */ +#define DLT_PPI 192 + +/* + * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header; + * requested by Charles Clancy. + */ +#define DLT_IEEE802_16_MAC_CPS_RADIO 193 + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . + * The DLT_ is used for internal communication with a + * integrated service module (ISM). + */ +#define DLT_JUNIPER_ISM 194 + +/* + * IEEE 802.15.4, exactly as it appears in the spec (no padding, no + * nothing); requested by Mikko Saarnivala . + * For this one, we expect the FCS to be present at the end of the frame; + * if the frame has no FCS, DLT_IEEE802_15_4_NOFCS should be used. + */ +#define DLT_IEEE802_15_4 195 + +/* + * Various link-layer types, with a pseudo-header, for SITA + * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com). + */ +#define DLT_SITA 196 + +/* + * Various link-layer types, with a pseudo-header, for Endace DAG cards; + * encapsulates Endace ERF records. Requested by Stephen Donnelly + * . + */ +#define DLT_ERF 197 + +/* + * Special header prepended to Ethernet packets when capturing from a + * u10 Networks board. Requested by Phil Mulholland + * . + */ +#define DLT_RAIF1 198 + +/* + * IPMB packet for IPMI, beginning with the I2C slave address, followed + * by the netFn and LUN, etc.. Requested by Chanthy Toeung + * . + */ +#define DLT_IPMB 199 + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . + * The DLT_ is used for capturing data on a secure tunnel interface. + */ +#define DLT_JUNIPER_ST 200 + +/* + * Bluetooth HCI UART transport layer (part H:4), with pseudo-header + * that includes direction information; requested by Paolo Abeni. + */ +#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201 + +/* + * AX.25 packet with a 1-byte KISS header; see + * + * http://www.ax25.net/kiss.htm + * + * as per Richard Stearn . + */ +#define DLT_AX25_KISS 202 + +/* + * LAPD packets from an ISDN channel, starting with the address field, + * with no pseudo-header. + * Requested by Varuna De Silva . + */ +#define DLT_LAPD 203 + +/* + * Variants of various link-layer headers, with a one-byte direction + * pseudo-header prepended - zero means "received by this host", + * non-zero (any non-zero value) means "sent by this host" - as per + * Will Barker . + */ +#define DLT_PPP_WITH_DIR 204 /* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */ +#define DLT_C_HDLC_WITH_DIR 205 /* Cisco HDLC */ +#define DLT_FRELAY_WITH_DIR 206 /* Frame Relay */ +#define DLT_LAPB_WITH_DIR 207 /* LAPB */ + +/* + * 208 is reserved for an as-yet-unspecified proprietary link-layer + * type, as requested by Will Barker. + */ + +/* + * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman + * . + */ +#define DLT_IPMB_LINUX 209 + +/* + * FlexRay automotive bus - http://www.flexray.com/ - as requested + * by Hannes Kaelber . + */ +#define DLT_FLEXRAY 210 + +/* + * Media Oriented Systems Transport (MOST) bus for multimedia + * transport - http://www.mostcooperation.com/ - as requested + * by Hannes Kaelber . + */ +#define DLT_MOST 211 + +/* + * Local Interconnect Network (LIN) bus for vehicle networks - + * http://www.lin-subbus.org/ - as requested by Hannes Kaelber + * . + */ +#define DLT_LIN 212 + +/* + * X2E-private data link type used for serial line capture, + * as requested by Hannes Kaelber . + */ +#define DLT_X2E_SERIAL 213 + +/* + * X2E-private data link type used for the Xoraya data logger + * family, as requested by Hannes Kaelber . + */ +#define DLT_X2E_XORAYA 214 + +/* + * IEEE 802.15.4, exactly as it appears in the spec (no padding, no + * nothing), but with the PHY-level data for non-ASK PHYs (4 octets + * of 0 as preamble, one octet of SFD, one octet of frame length+ + * reserved bit, and then the MAC-layer data, starting with the + * frame control field). + * + * Requested by Max Filippov . + */ +#define DLT_IEEE802_15_4_NONASK_PHY 215 + +/* + * David Gibson requested this for + * captures from the Linux kernel /dev/input/eventN devices. This + * is used to communicate keystrokes and mouse movements from the + * Linux kernel to display systems, such as Xorg. + */ +#define DLT_LINUX_EVDEV 216 + +/* + * GSM Um and Abis interfaces, preceded by a "gsmtap" header. + * + * Requested by Harald Welte . + */ +#define DLT_GSMTAP_UM 217 +#define DLT_GSMTAP_ABIS 218 + +/* + * MPLS, with an MPLS label as the link-layer header. + * Requested by Michele Marchetto on behalf + * of OpenBSD. + */ +#define DLT_MPLS 219 + +/* + * USB packets, beginning with a Linux USB header, with the USB header + * padded to 64 bytes; required for memory-mapped access. + */ +#define DLT_USB_LINUX_MMAPPED 220 + +/* + * DECT packets, with a pseudo-header; requested by + * Matthias Wenzel . + */ +#define DLT_DECT 221 + +/* + * From: "Lidwa, Eric (GSFC-582.0)[SGT INC]" + * Date: Mon, 11 May 2009 11:18:30 -0500 + * + * DLT_AOS. We need it for AOS Space Data Link Protocol. + * I have already written dissectors for but need an OK from + * legal before I can submit a patch. + * + */ +#define DLT_AOS 222 + +/* + * Wireless HART (Highway Addressable Remote Transducer) + * From the HART Communication Foundation + * IES/PAS 62591 + * + * Requested by Sam Roberts . + */ +#define DLT_WIHART 223 + +/* + * Fibre Channel FC-2 frames, beginning with a Frame_Header. + * Requested by Kahou Lei . + */ +#define DLT_FC_2 224 + +/* + * Fibre Channel FC-2 frames, beginning with an encoding of the + * SOF, and ending with an encoding of the EOF. + * + * The encodings represent the frame delimiters as 4-byte sequences + * representing the corresponding ordered sets, with K28.5 + * represented as 0xBC, and the D symbols as the corresponding + * byte values; for example, SOFi2, which is K28.5 - D21.5 - D1.2 - D21.2, + * is represented as 0xBC 0xB5 0x55 0x55. + * + * Requested by Kahou Lei . + */ +#define DLT_FC_2_WITH_FRAME_DELIMS 225 + +/* + * Solaris ipnet pseudo-header; requested by Darren Reed . + * + * The pseudo-header starts with a one-byte version number; for version 2, + * the pseudo-header is: + * + * struct dl_ipnetinfo { + * u_int8_t dli_version; + * u_int8_t dli_family; + * u_int16_t dli_htype; + * u_int32_t dli_pktlen; + * u_int32_t dli_ifindex; + * u_int32_t dli_grifindex; + * u_int32_t dli_zsrc; + * u_int32_t dli_zdst; + * }; + * + * dli_version is 2 for the current version of the pseudo-header. + * + * dli_family is a Solaris address family value, so it's 2 for IPv4 + * and 26 for IPv6. + * + * dli_htype is a "hook type" - 0 for incoming packets, 1 for outgoing + * packets, and 2 for packets arriving from another zone on the same + * machine. + * + * dli_pktlen is the length of the packet data following the pseudo-header + * (so the captured length minus dli_pktlen is the length of the + * pseudo-header, assuming the entire pseudo-header was captured). + * + * dli_ifindex is the interface index of the interface on which the + * packet arrived. + * + * dli_grifindex is the group interface index number (for IPMP interfaces). + * + * dli_zsrc is the zone identifier for the source of the packet. + * + * dli_zdst is the zone identifier for the destination of the packet. + * + * A zone number of 0 is the global zone; a zone number of 0xffffffff + * means that the packet arrived from another host on the network, not + * from another zone on the same machine. + * + * An IPv4 or IPv6 datagram follows the pseudo-header; dli_family indicates + * which of those it is. + */ +#define DLT_IPNET 226 + +/* + * CAN (Controller Area Network) frames, with a pseudo-header as supplied + * by Linux SocketCAN. See Documentation/networking/can.txt in the Linux + * source. + * + * Requested by Felix Obenhuber . + */ +#define DLT_CAN_SOCKETCAN 227 + +/* + * Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies + * whether it's v4 or v6. Requested by Darren Reed . + */ +#define DLT_IPV4 228 +#define DLT_IPV6 229 + +/* + * IEEE 802.15.4, exactly as it appears in the spec (no padding, no + * nothing), and with no FCS at the end of the frame; requested by + * Jon Smirl . + */ +#define DLT_IEEE802_15_4_NOFCS 230 + +/* + * Raw D-Bus: + * + * http://www.freedesktop.org/wiki/Software/dbus + * + * messages: + * + * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages + * + * starting with the endianness flag, followed by the message type, etc., + * but without the authentication handshake before the message sequence: + * + * http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol + * + * Requested by Martin Vidner . + */ +#define DLT_DBUS 231 + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . + */ +#define DLT_JUNIPER_VS 232 +#define DLT_JUNIPER_SRX_E2E 233 +#define DLT_JUNIPER_FIBRECHANNEL 234 + +/* + * DVB-CI (DVB Common Interface for communication between a PC Card + * module and a DVB receiver). See + * + * http://www.kaiser.cx/pcap-dvbci.html + * + * for the specification. + * + * Requested by Martin Kaiser . + */ +#define DLT_DVB_CI 235 + +/* + * Variant of 3GPP TS 27.010 multiplexing protocol (similar to, but + * *not* the same as, 27.010). Requested by Hans-Christoph Schemmel + * . + */ +#define DLT_MUX27010 236 + +/* + * STANAG 5066 D_PDUs. Requested by M. Baris Demiray + * . + */ +#define DLT_STANAG_5066_D_PDU 237 + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . + */ +#define DLT_JUNIPER_ATM_CEMIC 238 + +/* + * NetFilter LOG messages + * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets) + * + * Requested by Jakub Zawadzki + */ +#define DLT_NFLOG 239 + +/* + * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type + * for Ethernet packets with a 4-byte pseudo-header and always + * with the payload including the FCS, as supplied by their + * netANALYZER hardware and software. + * + * Requested by Holger P. Frommer + */ +#define DLT_NETANALYZER 240 + +/* + * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type + * for Ethernet packets with a 4-byte pseudo-header and FCS and + * with the Ethernet header preceded by 7 bytes of preamble and + * 1 byte of SFD, as supplied by their netANALYZER hardware and + * software. + * + * Requested by Holger P. Frommer + */ +#define DLT_NETANALYZER_TRANSPARENT 241 + +/* + * IP-over-InfiniBand, as specified by RFC 4391. + * + * Requested by Petr Sumbera . + */ +#define DLT_IPOIB 242 + +/* + * MPEG-2 transport stream (ISO 13818-1/ITU-T H.222.0). + * + * Requested by Guy Martin . + */ +#define DLT_MPEG_2_TS 243 + +/* + * ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as + * used by their ng40 protocol tester. + * + * Requested by Jens Grimmer . + */ +#define DLT_NG40 244 + +/* + * Pseudo-header giving adapter number and flags, followed by an NFC + * (Near-Field Communications) Logical Link Control Protocol (LLCP) PDU, + * as specified by NFC Forum Logical Link Control Protocol Technical + * Specification LLCP 1.1. + * + * Requested by Mike Wakerly . + */ +#define DLT_NFC_LLCP 245 + +/* + * 245 is used as LINKTYPE_PFSYNC; do not use it for any other purpose. + * + * DLT_PFSYNC has different values on different platforms, and all of + * them collide with something used elsewhere. On platforms that + * don't already define it, define it as 245. + */ +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) && !defined(__APPLE__) +#define DLT_PFSYNC 246 +#endif + +/* + * Raw InfiniBand packets, starting with the Local Routing Header. + * + * Requested by Oren Kladnitsky . + */ +#define DLT_INFINIBAND 247 + +/* + * SCTP, with no lower-level protocols (i.e., no IPv4 or IPv6). + * + * Requested by Michael Tuexen . + */ +#define DLT_SCTP 248 + +/* + * USB packets, beginning with a USBPcap header. + * + * Requested by Tomasz Mon + */ +#define DLT_USBPCAP 249 + +/* + * Schweitzer Engineering Laboratories "RTAC" product serial-line + * packets. + * + * Requested by Chris Bontje . + */ +#define DLT_RTAC_SERIAL 250 + +/* + * Bluetooth Low Energy air interface link-layer packets. + * + * Requested by Mike Kershaw . + */ +#define DLT_BLUETOOTH_LE_LL 251 + +/* + * DLT type for upper-protocol layer PDU saves from wireshark. + * + * the actual contents are determined by two TAGs stored with each + * packet: + * EXP_PDU_TAG_LINKTYPE the link type (LINKTYPE_ value) of the + * original packet. + * + * EXP_PDU_TAG_PROTO_NAME the name of the wireshark dissector + * that can make sense of the data stored. + */ +#define DLT_WIRESHARK_UPPER_PDU 252 + +#define DLT_MATCHING_MAX 252 /* highest value in the "matching" range */ + +/* + * DLT and savefile link type values are split into a class and + * a member of that class. A class value of 0 indicates a regular + * DLT_/LINKTYPE_ value. + */ +#define DLT_CLASS(x) ((x) & 0x03ff0000) + +/* + * NetBSD-specific generic "raw" link type. The class value indicates + * that this is the generic raw type, and the lower 16 bits are the + * address family we're dealing with. Those values are NetBSD-specific; + * do not assume that they correspond to AF_ values for your operating + * system. + */ +#define DLT_CLASS_NETBSD_RAWAF 0x02240000 +#define DLT_NETBSD_RAWAF(af) (DLT_CLASS_NETBSD_RAWAF | (af)) +#define DLT_NETBSD_RAWAF_AF(x) ((x) & 0x0000ffff) +#define DLT_IS_NETBSD_RAWAF(x) (DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF) + + +/* + * The instruction encodings. + */ +/* instruction classes */ +#define BPF_CLASS(code) ((code) & 0x07) +#define BPF_LD 0x00 +#define BPF_LDX 0x01 +#define BPF_ST 0x02 +#define BPF_STX 0x03 +#define BPF_ALU 0x04 +#define BPF_JMP 0x05 +#define BPF_RET 0x06 +#define BPF_MISC 0x07 + +/* ld/ldx fields */ +#define BPF_SIZE(code) ((code) & 0x18) +#define BPF_W 0x00 +#define BPF_H 0x08 +#define BPF_B 0x10 +#define BPF_MODE(code) ((code) & 0xe0) +#define BPF_IMM 0x00 +#define BPF_ABS 0x20 +#define BPF_IND 0x40 +#define BPF_MEM 0x60 +#define BPF_LEN 0x80 +#define BPF_MSH 0xa0 + +/* alu/jmp fields */ +#define BPF_OP(code) ((code) & 0xf0) +#define BPF_ADD 0x00 +#define BPF_SUB 0x10 +#define BPF_MUL 0x20 +#define BPF_DIV 0x30 +#define BPF_OR 0x40 +#define BPF_AND 0x50 +#define BPF_LSH 0x60 +#define BPF_RSH 0x70 +#define BPF_NEG 0x80 +#define BPF_JA 0x00 +#define BPF_JEQ 0x10 +#define BPF_JGT 0x20 +#define BPF_JGE 0x30 +#define BPF_JSET 0x40 +#define BPF_SRC(code) ((code) & 0x08) +#define BPF_K 0x00 +#define BPF_X 0x08 + +/* ret - BPF_K and BPF_X also apply */ +#define BPF_RVAL(code) ((code) & 0x18) +#define BPF_A 0x10 + +/* misc */ +#define BPF_MISCOP(code) ((code) & 0xf8) +#define BPF_TAX 0x00 +#define BPF_TXA 0x80 + +/* + * The instruction data structure. + */ +struct bpf_insn { + u_short code; + u_char jt; + u_char jf; + bpf_u_int32 k; +}; + +/* + * Macros for insn array initializers. + */ +#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } +#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } + +#if __STDC__ || defined(__cplusplus) +extern int bpf_validate(const struct bpf_insn *, int); +extern u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int); +#else +extern int bpf_validate(); +extern u_int bpf_filter(); +#endif + +/* + * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). + */ +#define BPF_MEMWORDS 16 + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(_NET_BPF_H_) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h) */ diff --git a/pde-test-host/pde-test-host/include/pcap/ipnet.h b/pde-test-host/pde-test-host/include/pcap/ipnet.h new file mode 100644 index 0000000..5330847 --- /dev/null +++ b/pde-test-host/pde-test-host/include/pcap/ipnet.h @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define IPH_AF_INET 2 /* Matches Solaris's AF_INET */ +#define IPH_AF_INET6 26 /* Matches Solaris's AF_INET6 */ + +#define IPNET_OUTBOUND 1 +#define IPNET_INBOUND 2 diff --git a/pde-test-host/pde-test-host/include/pcap/namedb.h b/pde-test-host/pde-test-host/include/pcap/namedb.h new file mode 100644 index 0000000..e314557 --- /dev/null +++ b/pde-test-host/pde-test-host/include/pcap/namedb.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1994, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap/namedb.h,v 1.1 2006-10-04 18:09:22 guy Exp $ (LBL) + */ + +#ifndef lib_pcap_namedb_h +#define lib_pcap_namedb_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * As returned by the pcap_next_etherent() + * XXX this stuff doesn't belong in this interface, but this + * library already must do name to address translation, so + * on systems that don't have support for /etc/ethers, we + * export these hooks since they'll + */ +struct pcap_etherent { + u_char addr[6]; + char name[122]; +}; +#ifndef PCAP_ETHERS_FILE +#define PCAP_ETHERS_FILE "/etc/ethers" +#endif +struct pcap_etherent *pcap_next_etherent(FILE *); +u_char *pcap_ether_hostton(const char*); +u_char *pcap_ether_aton(const char *); + +bpf_u_int32 **pcap_nametoaddr(const char *); +#ifdef INET6 +struct addrinfo *pcap_nametoaddrinfo(const char *); +#endif +bpf_u_int32 pcap_nametonetaddr(const char *); + +int pcap_nametoport(const char *, int *, int *); +int pcap_nametoportrange(const char *, int *, int *, int *); +int pcap_nametoproto(const char *); +int pcap_nametoeproto(const char *); +int pcap_nametollc(const char *); +/* + * If a protocol is unknown, PROTO_UNDEF is returned. + * Also, pcap_nametoport() returns the protocol along with the port number. + * If there are ambiguous entried in /etc/services (i.e. domain + * can be either tcp or udp) PROTO_UNDEF is returned. + */ +#define PROTO_UNDEF -1 + +/* XXX move these to pcap-int.h? */ +int __pcap_atodn(const char *, bpf_u_int32 *); +int __pcap_atoin(const char *, bpf_u_int32 *); +u_short __pcap_nametodnaddr(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pde-test-host/pde-test-host/include/pcap/pcap.h b/pde-test-host/pde-test-host/include/pcap/pcap.h new file mode 100644 index 0000000..896c901 --- /dev/null +++ b/pde-test-host/pde-test-host/include/pcap/pcap.h @@ -0,0 +1,484 @@ +/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ +/* + * Copyright (c) 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.15 2008-10-06 15:27:32 gianluca Exp $ (LBL) + */ + +#ifndef lib_pcap_pcap_h +#define lib_pcap_pcap_h + +#if defined(WIN32) + #include +#elif defined(MSDOS) + #include + #include /* u_int, u_char etc. */ +#else /* UN*X */ + #include + #include +#endif /* WIN32/MSDOS/UN*X */ + +#ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H +#include +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Version number of the current version of the pcap file format. + * + * NOTE: this is *NOT* the version number of the libpcap library. + * To fetch the version information for the version of libpcap + * you're using, use pcap_lib_version(). + */ +#define PCAP_VERSION_MAJOR 2 +#define PCAP_VERSION_MINOR 4 + +#define PCAP_ERRBUF_SIZE 256 + +/* + * Compatibility for systems that have a bpf.h that + * predates the bpf typedefs for 64-bit support. + */ +#if BPF_RELEASE - 0 < 199406 +typedef int bpf_int32; +typedef u_int bpf_u_int32; +#endif + +typedef struct pcap pcap_t; +typedef struct pcap_dumper pcap_dumper_t; +typedef struct pcap_if pcap_if_t; +typedef struct pcap_addr pcap_addr_t; + +/* + * The first record in the file contains saved values for some + * of the flags used in the printout phases of tcpdump. + * Many fields here are 32 bit ints so compilers won't insert unwanted + * padding; these files need to be interchangeable across architectures. + * + * Do not change the layout of this structure, in any way (this includes + * changes that only affect the length of fields in this structure). + * + * Also, do not change the interpretation of any of the members of this + * structure, in any way (this includes using values other than + * LINKTYPE_ values, as defined in "savefile.c", in the "linktype" + * field). + * + * Instead: + * + * introduce a new structure for the new format, if the layout + * of the structure changed; + * + * send mail to "tcpdump-workers@lists.tcpdump.org", requesting + * a new magic number for your new capture file format, and, when + * you get the new magic number, put it in "savefile.c"; + * + * use that magic number for save files with the changed file + * header; + * + * make the code in "savefile.c" capable of reading files with + * the old file header as well as files with the new file header + * (using the magic number to determine the header format). + * + * Then supply the changes by forking the branch at + * + * https://github.com/the-tcpdump-group/libpcap/issues + * + * and issuing a pull request, so that future versions of libpcap and + * programs that use it (such as tcpdump) will be able to read your new + * capture file format. + */ +struct pcap_file_header { + bpf_u_int32 magic; + u_short version_major; + u_short version_minor; + bpf_int32 thiszone; /* gmt to local correction */ + bpf_u_int32 sigfigs; /* accuracy of timestamps */ + bpf_u_int32 snaplen; /* max length saved portion of each pkt */ + bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ +}; + +/* + * Macros for the value returned by pcap_datalink_ext(). + * + * If LT_FCS_LENGTH_PRESENT(x) is true, the LT_FCS_LENGTH(x) macro + * gives the FCS length of packets in the capture. + */ +#define LT_FCS_LENGTH_PRESENT(x) ((x) & 0x04000000) +#define LT_FCS_LENGTH(x) (((x) & 0xF0000000) >> 28) +#define LT_FCS_DATALINK_EXT(x) ((((x) & 0xF) << 28) | 0x04000000) + +typedef enum { + PCAP_D_INOUT = 0, + PCAP_D_IN, + PCAP_D_OUT +} pcap_direction_t; + +/* + * Generic per-packet information, as supplied by libpcap. + * + * The time stamp can and should be a "struct timeval", regardless of + * whether your system supports 32-bit tv_sec in "struct timeval", + * 64-bit tv_sec in "struct timeval", or both if it supports both 32-bit + * and 64-bit applications. The on-disk format of savefiles uses 32-bit + * tv_sec (and tv_usec); this structure is irrelevant to that. 32-bit + * and 64-bit versions of libpcap, even if they're on the same platform, + * should supply the appropriate version of "struct timeval", even if + * that's not what the underlying packet capture mechanism supplies. + */ +struct pcap_pkthdr { + struct timeval ts; /* time stamp */ + bpf_u_int32 caplen; /* length of portion present */ + bpf_u_int32 len; /* length this packet (off wire) */ +}; + +/* + * As returned by the pcap_stats() + */ +struct pcap_stat { + u_int ps_recv; /* number of packets received */ + u_int ps_drop; /* number of packets dropped */ + u_int ps_ifdrop; /* drops by interface -- only supported on some platforms */ +#ifdef WIN32 + u_int bs_capt; /* number of packets that reach the application */ +#endif /* WIN32 */ +}; + +#ifdef MSDOS +/* + * As returned by the pcap_stats_ex() + */ +struct pcap_stat_ex { + u_long rx_packets; /* total packets received */ + u_long tx_packets; /* total packets transmitted */ + u_long rx_bytes; /* total bytes received */ + u_long tx_bytes; /* total bytes transmitted */ + u_long rx_errors; /* bad packets received */ + u_long tx_errors; /* packet transmit problems */ + u_long rx_dropped; /* no space in Rx buffers */ + u_long tx_dropped; /* no space available for Tx */ + u_long multicast; /* multicast packets received */ + u_long collisions; + + /* detailed rx_errors: */ + u_long rx_length_errors; + u_long rx_over_errors; /* receiver ring buff overflow */ + u_long rx_crc_errors; /* recv'd pkt with crc error */ + u_long rx_frame_errors; /* recv'd frame alignment error */ + u_long rx_fifo_errors; /* recv'r fifo overrun */ + u_long rx_missed_errors; /* recv'r missed packet */ + + /* detailed tx_errors */ + u_long tx_aborted_errors; + u_long tx_carrier_errors; + u_long tx_fifo_errors; + u_long tx_heartbeat_errors; + u_long tx_window_errors; + }; +#endif + +/* + * Item in a list of interfaces. + */ +struct pcap_if { + struct pcap_if *next; + char *name; /* name to hand to "pcap_open_live()" */ + char *description; /* textual description of interface, or NULL */ + struct pcap_addr *addresses; + bpf_u_int32 flags; /* PCAP_IF_ interface flags */ +}; + +#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */ + +/* + * Representation of an interface address. + */ +struct pcap_addr { + struct pcap_addr *next; + struct sockaddr *addr; /* address */ + struct sockaddr *netmask; /* netmask for that address */ + struct sockaddr *broadaddr; /* broadcast address for that address */ + struct sockaddr *dstaddr; /* P2P destination address for that address */ +}; + +typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, + const u_char *); + +/* + * Error codes for the pcap API. + * These will all be negative, so you can check for the success or + * failure of a call that returns these codes by checking for a + * negative value. + */ +#define PCAP_ERROR -1 /* generic error code */ +#define PCAP_ERROR_BREAK -2 /* loop terminated by pcap_breakloop */ +#define PCAP_ERROR_NOT_ACTIVATED -3 /* the capture needs to be activated */ +#define PCAP_ERROR_ACTIVATED -4 /* the operation can't be performed on already activated captures */ +#define PCAP_ERROR_NO_SUCH_DEVICE -5 /* no such device exists */ +#define PCAP_ERROR_RFMON_NOTSUP -6 /* this device doesn't support rfmon (monitor) mode */ +#define PCAP_ERROR_NOT_RFMON -7 /* operation supported only in monitor mode */ +#define PCAP_ERROR_PERM_DENIED -8 /* no permission to open the device */ +#define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */ +#define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10 /* this device doesn't support setting the time stamp type */ +#define PCAP_ERROR_PROMISC_PERM_DENIED -11 /* you don't have permission to capture in promiscuous mode */ +#define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12 /* the requested time stamp precision is not supported */ + +/* + * Warning codes for the pcap API. + * These will all be positive and non-zero, so they won't look like + * errors. + */ +#define PCAP_WARNING 1 /* generic warning code */ +#define PCAP_WARNING_PROMISC_NOTSUP 2 /* this device doesn't support promiscuous mode */ +#define PCAP_WARNING_TSTAMP_TYPE_NOTSUP 3 /* the requested time stamp type is not supported */ + +/* + * Value to pass to pcap_compile() as the netmask if you don't know what + * the netmask is. + */ +#define PCAP_NETMASK_UNKNOWN 0xffffffff + +char *pcap_lookupdev(char *); +int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *); + +pcap_t *pcap_create(const char *, char *); +int pcap_set_snaplen(pcap_t *, int); +int pcap_set_promisc(pcap_t *, int); +int pcap_can_set_rfmon(pcap_t *); +int pcap_set_rfmon(pcap_t *, int); +int pcap_set_timeout(pcap_t *, int); +int pcap_set_tstamp_type(pcap_t *, int); +int pcap_set_immediate_mode(pcap_t *, int); +int pcap_set_buffer_size(pcap_t *, int); +int pcap_set_tstamp_precision(pcap_t *, int); +int pcap_get_tstamp_precision(pcap_t *); +int pcap_activate(pcap_t *); + +int pcap_list_tstamp_types(pcap_t *, int **); +void pcap_free_tstamp_types(int *); +int pcap_tstamp_type_name_to_val(const char *); +const char *pcap_tstamp_type_val_to_name(int); +const char *pcap_tstamp_type_val_to_description(int); + +/* + * Time stamp types. + * Not all systems and interfaces will necessarily support all of these. + * + * A system that supports PCAP_TSTAMP_HOST is offering time stamps + * provided by the host machine, rather than by the capture device, + * but not committing to any characteristics of the time stamp; + * it will not offer any of the PCAP_TSTAMP_HOST_ subtypes. + * + * PCAP_TSTAMP_HOST_LOWPREC is a time stamp, provided by the host machine, + * that's low-precision but relatively cheap to fetch; it's normally done + * using the system clock, so it's normally synchronized with times you'd + * fetch from system calls. + * + * PCAP_TSTAMP_HOST_HIPREC is a time stamp, provided by the host machine, + * that's high-precision; it might be more expensive to fetch. It might + * or might not be synchronized with the system clock, and might have + * problems with time stamps for packets received on different CPUs, + * depending on the platform. + * + * PCAP_TSTAMP_ADAPTER is a high-precision time stamp supplied by the + * capture device; it's synchronized with the system clock. + * + * PCAP_TSTAMP_ADAPTER_UNSYNCED is a high-precision time stamp supplied by + * the capture device; it's not synchronized with the system clock. + * + * Note that time stamps synchronized with the system clock can go + * backwards, as the system clock can go backwards. If a clock is + * not in sync with the system clock, that could be because the + * system clock isn't keeping accurate time, because the other + * clock isn't keeping accurate time, or both. + * + * Note that host-provided time stamps generally correspond to the + * time when the time-stamping code sees the packet; this could + * be some unknown amount of time after the first or last bit of + * the packet is received by the network adapter, due to batching + * of interrupts for packet arrival, queueing delays, etc.. + */ +#define PCAP_TSTAMP_HOST 0 /* host-provided, unknown characteristics */ +#define PCAP_TSTAMP_HOST_LOWPREC 1 /* host-provided, low precision */ +#define PCAP_TSTAMP_HOST_HIPREC 2 /* host-provided, high precision */ +#define PCAP_TSTAMP_ADAPTER 3 /* device-provided, synced with the system clock */ +#define PCAP_TSTAMP_ADAPTER_UNSYNCED 4 /* device-provided, not synced with the system clock */ + +/* + * Time stamp resolution types. + * Not all systems and interfaces will necessarily support all of these + * resolutions when doing live captures; all of them can be requested + * when reading a savefile. + */ +#define PCAP_TSTAMP_PRECISION_MICRO 0 /* use timestamps with microsecond precision, default */ +#define PCAP_TSTAMP_PRECISION_NANO 1 /* use timestamps with nanosecond precision */ + +pcap_t *pcap_open_live(const char *, int, int, int, char *); +pcap_t *pcap_open_dead(int, int); +pcap_t *pcap_open_dead_with_tstamp_precision(int, int, u_int); +pcap_t *pcap_open_offline_with_tstamp_precision(const char *, u_int, char *); +pcap_t *pcap_open_offline(const char *, char *); +#if defined(WIN32) +pcap_t *pcap_hopen_offline_with_tstamp_precision(intptr_t, u_int, char *); +pcap_t *pcap_hopen_offline(intptr_t, char *); +#if !defined(LIBPCAP_EXPORTS) +#define pcap_fopen_offline_with_tstamp_precision(f,p,b) \ + pcap_hopen_offline_with_tstamp_precision(_get_osfhandle(_fileno(f)), p, b) +#define pcap_fopen_offline(f,b) \ + pcap_hopen_offline(_get_osfhandle(_fileno(f)), b) +#else /*LIBPCAP_EXPORTS*/ +static pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *); +static pcap_t *pcap_fopen_offline(FILE *, char *); +#endif +#else /*WIN32*/ +pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *); +pcap_t *pcap_fopen_offline(FILE *, char *); +#endif /*WIN32*/ + +void pcap_close(pcap_t *); +int pcap_loop(pcap_t *, int, pcap_handler, u_char *); +int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *); +const u_char* + pcap_next(pcap_t *, struct pcap_pkthdr *); +int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **); +void pcap_breakloop(pcap_t *); +int pcap_stats(pcap_t *, struct pcap_stat *); +int pcap_setfilter(pcap_t *, struct bpf_program *); +int pcap_setdirection(pcap_t *, pcap_direction_t); +int pcap_getnonblock(pcap_t *, char *); +int pcap_setnonblock(pcap_t *, int, char *); +int pcap_inject(pcap_t *, const void *, size_t); +int pcap_sendpacket(pcap_t *, const u_char *, int); +const char *pcap_statustostr(int); +const char *pcap_strerror(int); +char *pcap_geterr(pcap_t *); +void pcap_perror(pcap_t *, char *); +int pcap_compile(pcap_t *, struct bpf_program *, const char *, int, + bpf_u_int32); +int pcap_compile_nopcap(int, int, struct bpf_program *, + const char *, int, bpf_u_int32); +void pcap_freecode(struct bpf_program *); +int pcap_offline_filter(const struct bpf_program *, + const struct pcap_pkthdr *, const u_char *); +int pcap_datalink(pcap_t *); +int pcap_datalink_ext(pcap_t *); +int pcap_list_datalinks(pcap_t *, int **); +int pcap_set_datalink(pcap_t *, int); +void pcap_free_datalinks(int *); +int pcap_datalink_name_to_val(const char *); +const char *pcap_datalink_val_to_name(int); +const char *pcap_datalink_val_to_description(int); +int pcap_snapshot(pcap_t *); +int pcap_is_swapped(pcap_t *); +int pcap_major_version(pcap_t *); +int pcap_minor_version(pcap_t *); + +/* XXX */ +FILE *pcap_file(pcap_t *); +int pcap_fileno(pcap_t *); + +pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); +pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp); +FILE *pcap_dump_file(pcap_dumper_t *); +long pcap_dump_ftell(pcap_dumper_t *); +int pcap_dump_flush(pcap_dumper_t *); +void pcap_dump_close(pcap_dumper_t *); +void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); + +int pcap_findalldevs(pcap_if_t **, char *); +void pcap_freealldevs(pcap_if_t *); + +const char *pcap_lib_version(void); + +/* + * On at least some versions of NetBSD, we don't want to declare + * bpf_filter() here, as it's also be declared in , with a + * different signature, but, on other BSD-flavored UN*Xes, it's not + * declared in , so we *do* want to declare it here, so it's + * declared when we build pcap-bpf.c. + */ +#ifndef __NetBSD__ +u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int); +#endif +int bpf_validate(const struct bpf_insn *f, int len); +char *bpf_image(const struct bpf_insn *, int); +void bpf_dump(const struct bpf_program *, int); + +#if defined(WIN32) + +/* + * Win32 definitions + */ + +int pcap_setbuff(pcap_t *p, int dim); +int pcap_setmode(pcap_t *p, int mode); +int pcap_setmintocopy(pcap_t *p, int size); +Adapter *pcap_get_adapter(pcap_t *p); + +#ifdef WPCAP +/* Include file with the wpcap-specific extensions */ +#include +#endif /* WPCAP */ + +#define MODE_CAPT 0 +#define MODE_STAT 1 +#define MODE_MON 2 + +#elif defined(MSDOS) + +/* + * MS-DOS definitions + */ + +int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *); +void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait); +u_long pcap_mac_packets (void); + +#else /* UN*X */ + +/* + * UN*X definitions + */ + +int pcap_get_selectable_fd(pcap_t *); + +#endif /* WIN32/MSDOS/UN*X */ + +#ifdef __cplusplus +} +#endif + +#endif /* lib_pcap_pcap_h */ diff --git a/pde-test-host/pde-test-host/include/pcap/vlan.h b/pde-test-host/pde-test-host/include/pcap/vlan.h new file mode 100644 index 0000000..41aa8c7 --- /dev/null +++ b/pde-test-host/pde-test-host/include/pcap/vlan.h @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap/vlan.h,v 1.1 2008-08-06 07:45:00 guy Exp $ + */ + +#ifndef lib_pcap_vlan_h +#define lib_pcap_vlan_h + +struct vlan_tag { + u_int16_t vlan_tpid; /* ETH_P_8021Q */ + u_int16_t vlan_tci; /* VLAN TCI */ +}; + +#define VLAN_TAG_LEN 4 + +#endif diff --git a/pde-test-host/pde-test-host/include/types.h b/pde-test-host/pde-test-host/include/types.h new file mode 100644 index 0000000..de09c94 --- /dev/null +++ b/pde-test-host/pde-test-host/include/types.h @@ -0,0 +1,300 @@ +/* + * $Id: types.h,v 1.25 Broadcom SDK $ + * $Copyright: (c) 2018 Broadcom. + * Broadcom Proprietary and Confidential. All rights reserved.$ + * + * File: types.h + * Purpose: SAL type definitions + */ + +#ifdef SDK_SOURCE_CHECK +#include +#endif + +#ifndef _SAL_TYPES_H +#define _SAL_TYPES_H + +#include + +/* + * Define platform-independent types + */ + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef DONT_CARE +#define DONT_CARE 0 +#endif + +#define VOL volatile + +/* + * We need to skip these defs if we are compiling for the uKernel. + */ +#ifndef BCM_UKERNEL + +/* + * Define unsigned and signed integers with guaranteed sizes. + * Adjust if your compiler uses different sizes for short or int. + */ + +typedef unsigned char uint8; /* 8-bit quantity */ +typedef unsigned short uint16; /* 16-bit quantity */ +typedef unsigned int uint32; /* 32-bit quantity */ +typedef COMPILER_UINT64 uint64; /* 64-bit quantity */ + +typedef signed char int8; /* 8-bit quantity */ +typedef signed short int16; /* 16-bit quantity */ +typedef signed int int32; /* 32-bit quantity */ +typedef COMPILER_INT64 int64; /* 64-bit quantity */ + +#endif + +#define SAL_UINT8_NOF_BITS (8) +#define SAL_UINT16_NOF_BITS (16) +#define SAL_UINT32_NOF_BITS (32) +#define SAL_UINT64_NOF_BITS (64) + +#define SAL_UINT8_MAX_BIT (SAL_UINT8_NOF_BITS - 1) +#define SAL_UINT16_MAX_BIT (SAL_UINT16_NOF_BITS - 1) +#define SAL_UINT32_MAX_BIT (SAL_UINT32_NOF_BITS - 1) +#define SAL_UINT64_MAX_BIT (SAL_UINT64_NOF_BITS - 1) + + + + + + +#define SAL_BIT(x) (1 << (x)) +#define SAL_RBIT(x) (~(1<<(x))) + +/******************************************* + * SET ALL BITS, BEGINNING AT BIT X, TO 1 * + *******************************************/ +#define SAL_FROM_BIT(x) (SAL_RBIT(x) + 1) + +/******************************************* + * SET ALL BITS UP TO BIT X (NOT INCLUDING * + * BIT X) TO 1. * + *******************************************/ +#define SAL_UPTO_BIT(x) (~(SAL_FROM_BIT(x))) + +/************************************************************** + * MACRO TO GET THE OFFSET OF AN ELEMENT IN A * + * GIVEN STRUCTURE TYPE. * + * 'X' IS THE TYPE OF THE STRUCTURE. * + * 'Y' IS THE THE ELEMENT (IN THE STRUCTURE) WHOSE * + * OFFSET WE NEED. * + * THE OFFSET RETURNS AS 'unsigned long'. * + **************************************************************/ +#define SAL_OFFSETOF(x,y) ((unsigned long)(&(((x *)0)->y))) + +/************************************************************** + * MACRO TO GET THE SIZE OF AN ELEMENT IN A * + * GIVEN STRUCTURE TYPE. * + * 'X' IS THE TYPE OF THE STRUCTURE. * + * 'Y' IS THE ELEMENT (IN THE STRUCTURE) WHOSE * + * SIZE (IN BYTES) WE NEED. * + * THE SIZE RETURNS AS 'unsigned long'. * + **************************************************************/ +#define SAL_SIZEOF(x,y) ((unsigned long)(sizeof(((x *)0)->y))) + +#define BITS2BYTES(x) (((x) + 7) / 8) +#define BITS2WORDS(x) (((x) + 31) / 32) + +#define BYTES2BITS(x) ((x) * 8) +#define BYTES2WORDS(x) (((x) + 3) / 4) + +#define WORDS2BITS(x) ((x) * 32) +#define WORDS2BYTES(x) ((x) * 4) + +#ifndef COUNTOF +#define COUNTOF(ary) ((int) (sizeof (ary) / sizeof ((ary)[0]))) +#endif + +#ifdef PTRS_ARE_64BITS +typedef uint64 sal_vaddr_t; /* Virtual address (Host address) */ +typedef uint64 sal_paddr_t; /* Physical address (PCI address) */ +#define PTR_TO_INT(x) ((uint32)(((sal_vaddr_t)(x))&0xFFFFFFFF)) +#define PTR_HI_TO_INT(x) ((uint32)((((sal_vaddr_t)(x))>>32)&0xFFFFFFFF)) + +#else +typedef uint32 sal_vaddr_t; /* Virtual address (Host address) */ +/* Physical address (PCI address) */ +#ifdef PHYS_ADDRS_ARE_64BITS +typedef uint64 sal_paddr_t; +#else +typedef uint32 sal_paddr_t; +#endif +#define PTR_TO_INT(x) ((uint32)(x)) +#define PTR_HI_TO_INT(x) (0) +#endif + +#define INT_TO_PTR(x) ((void *)((sal_vaddr_t)(x))) + +#define PTR_TO_UINTPTR(x) ((sal_vaddr_t)(x)) +#define UINTPTR_TO_PTR(x) ((void *)(x)) + +typedef union +{ + uint8 u8; + uint16 u16; + uint32 u32; + uint64 u64; + sal_paddr_t paddr; + sal_vaddr_t vaddr; + void *ptr; +} any_t; + +#define SAL_IP6_ADDRLEN (16) /* IPv6 address length in bytes. */ + +typedef uint8 sal_mac_addr_t[6]; /* MAC address */ +typedef uint32 sal_ip_addr_t; /* IP Address */ +typedef uint8 sal_ip6_addr_t[SAL_IP6_ADDRLEN]; /* IPv6 Address */ + +/* sal_mac_addr_t mac; Just generate a list of the macs for display */ +#define SAL_MAC_ADDR_LIST(mac) \ + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] + +/* sal_mac_addr_t m1, m2; True if equal */ +#define SAL_MAC_ADDR_EQUAL(m1, m2) (!sal_memcmp(m1, m2, sizeof(sal_mac_addr_t))) + +/* sal_mac_addr_t m1, m2; like memcmp, returns -1, 0, or 1 */ +#define SAL_MAC_ADDR_CMP(m1, m2) sal_memcmp(m1, m2, sizeof(sal_mac_addr_t)) + +#define SAL_MACADDR_STR_LEN 18 /* Formatted MAC address */ +#define SAL_IPADDR_STR_LEN 16 /* Formatted IP address */ + + +/* Adjust justification for uint32 writes to fields */ +/* dst is an array name of type uint32 [] */ +#define SAL_MAC_ADDR_TO_UINT32(mac, dst) do {\ + (dst)[0] = (((uint32)(mac)[2]) << 24 | \ + ((uint32)(mac)[3]) << 16 | \ + ((uint32)(mac)[4]) << 8 | \ + ((uint32)(mac)[5])); \ + (dst)[1] = (((uint32)(mac)[0]) << 8 | \ + ((uint32)(mac)[1])); \ + } while (0) + +/* Adjust justification for uint32 writes to fields */ +/* src is an array name of type uint32 [] */ +#define SAL_MAC_ADDR_FROM_UINT32(mac, src) do {\ + (mac)[0] = (uint8) ((src)[1] >> 8 & 0xff); \ + (mac)[1] = (uint8) ((src)[1] & 0xff); \ + (mac)[2] = (uint8) ((src)[0] >> 24); \ + (mac)[3] = (uint8) ((src)[0] >> 16 & 0xff); \ + (mac)[4] = (uint8) ((src)[0] >> 8 & 0xff); \ + (mac)[5] = (uint8) ((src)[0] & 0xff); \ + } while (0) + + +/* dst is a uint64 */ +#define SAL_MAC_ADDR_TO_UINT64(mac, dst) do { \ + uint32 _val[2]; \ + SAL_MAC_ADDR_TO_UINT32(mac, _val); \ + COMPILER_64_SET(dst, _val[1], _val[0]); \ + } while (0) + +/* src is a uint64 */ +#define SAL_MAC_ADDR_FROM_UINT64(mac, src) do { \ + uint32 _val[2]; \ + COMPILER_64_TO_32_LO(_val[0], src); \ + COMPILER_64_TO_32_HI(_val[1], src); \ + SAL_MAC_ADDR_FROM_UINT32(mac, _val); \ + } while (0) + + +/* Adjust IP6 justification for uint32 field accesses */ +/* + * These macros are used on IP6 "half addresses", being + * either the "upper" 64 bits or the "lower" 64 bits of + * an IPv6 address. + */ + +/* dst is an array name of type uint32 [] */ +#define SAL_IP6_ADDR_HALF_TO_UINT32(ip6, dst) do {\ + (dst)[1] = (((uint32)(ip6)[0]) << 24 | \ + ((uint32)(ip6)[1]) << 16 | \ + ((uint32)(ip6)[2]) << 8 | \ + ((uint32)(ip6)[3])); \ + (dst)[0] = (((uint32)(ip6)[4]) << 24 | \ + ((uint32)(ip6)[5]) << 16 | \ + ((uint32)(ip6)[6]) << 8 | \ + ((uint32)(ip6)[7])); \ + } while (0) + +/* src is an array name of type uint32 [] */ +#define SAL_IP6_ADDR_HALF_FROM_UINT32(ip6, src) do {\ + (ip6)[0] = (uint8) ((src)[1] >> 24); \ + (ip6)[1] = (uint8) ((src)[1] >> 16 & 0xff); \ + (ip6)[2] = (uint8) ((src)[1] >> 8 & 0xff); \ + (ip6)[3] = (uint8) ((src)[1] & 0xff); \ + (ip6)[4] = (uint8) ((src)[0] >> 24); \ + (ip6)[5] = (uint8) ((src)[0] >> 16 & 0xff); \ + (ip6)[6] = (uint8) ((src)[0] >> 8 & 0xff); \ + (ip6)[7] = (uint8) ((src)[0] & 0xff); \ + } while (0) + +/* + * These macros are used on full 128-bit IP6 addresses. + */ + +/* dst is an array name of type uint32 [] */ +#define SAL_IP6_ADDR_TO_UINT32(ip6, dst) do {\ + SAL_IP6_ADDR_HALF_TO_UINT32(&((ip6)[8]), (dst)); \ + SAL_IP6_ADDR_HALF_TO_UINT32((ip6), &((dst)[2])); \ + } while (0) + +/* src is an array name of type uint32 [] */ +#define SAL_IP6_ADDR_FROM_UINT32(ip6, src) do {\ + SAL_IP6_ADDR_HALF_FROM_UINT32(&((ip6)[8]), (src)); \ + SAL_IP6_ADDR_HALF_FROM_UINT32((ip6), &((src)[2])); \ + } while (0) + + +/* Device bus types */ +#define SAL_PCI_DEV_TYPE 0x00001 /* PCI device */ +#define SAL_SPI_DEV_TYPE 0x00002 /* SPI device */ +#define SAL_EB_DEV_TYPE 0x00004 /* EB device */ +#define SAL_ICS_DEV_TYPE 0x00008 /* ICS device */ +#define SAL_MII_DEV_TYPE 0x00010 /* MII device */ +#define SAL_RCPU_DEV_TYPE 0x00020 /* RCPU device */ +#define SAL_I2C_DEV_TYPE 0x00040 /* I2C device */ +#define SAL_AXI_DEV_TYPE 0x00080 /* AXI device */ +#define SAL_EMMI_DEV_TYPE 0x10000 /* EMMI device */ +#define SAL_DEV_BUS_TYPE_MASK 0xf00ff /* Odd for historical reasons */ + +/* Device types */ +#define SAL_SWITCH_DEV_TYPE 0x00100 /* Switch device */ +#define SAL_ETHER_DEV_TYPE 0x00200 /* Ethernet device */ +#define SAL_CPU_DEV_TYPE 0x00400 /* CPU device */ +#define SAL_DEV_TYPE_MASK 0x00f00 + +/* Access types */ +#define SAL_DEV_BUS_RD_16BIT 0x01000 /* 16 bit reads on bus */ +#define SAL_DEV_BUS_WR_16BIT 0x02000 /* 16 bit writes on bus */ +#define SAL_DEV_BUS_ALT 0x04000 /* Alternate access */ +#define SAL_DEV_BUS_MSI 0x08000 /* Message-signaled interrupts */ +#define SAL_DEV_FLAG_MASK 0x0f000 + +/* BDE reserved mask (cannot be used by SAL) */ +#define SAL_DEV_BDE_MASK 0xff000000 + +/* Backward compatibility */ +#define SAL_ET_DEV_TYPE SAL_MII_DEV_TYPE + +/* Special access addresses */ +#define SAL_DEV_OP_EMMI_INIT 0x0fff1000 + +#endif /* !_SAL_TYPES_H */ diff --git a/pde-test-host/pde-test-host/parse_port_config.py b/pde-test-host/pde-test-host/parse_port_config.py new file mode 100755 index 0000000..01b1f9d --- /dev/null +++ b/pde-test-host/pde-test-host/parse_port_config.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python +# +# parse_port_config.py +# +# Command-line utility for parsing SONiC database for port entries +# and generating a test_host.ini file for pde-test-host application +# + +try: + import sys + import os + import subprocess + import imp + import syslog + import types + import json + import logging + import errno +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +def get_port_config_file_name(hwsku=None, platform=None): + port_config_candidates = [] + port_config_candidates.append('/usr/share/sonic/hwsku/port_config.ini') + if hwsku: + if platform: + port_config_candidates.append(os.path.join('/usr/share/sonic/device', platform, hwsku, 'port_config.ini')) + port_config_candidates.append(os.path.join('/usr/share/sonic/platform', hwsku, 'port_config.ini')) + port_config_candidates.append(os.path.join('/usr/share/sonic', hwsku, 'port_config.ini')) + for candidate in port_config_candidates: + if os.path.isfile(candidate): + return candidate + return None + +def get_port_config(hwsku=None, platform=None, port_config_file=None): + if not port_config_file: + port_config_file = get_port_config_file_name(hwsku, platform) + if not port_config_file: + return ({}, {}) + return parse_port_config_file(port_config_file) + + +def parse_port_config_file(port_config_file): + port_names = {} + port_lanes = {} + port_alias = {} + port_index = {} + port_speed = {} + port_valid_speed = {} + # Default column definition + titles = ['name', 'lanes', 'alias', 'index' 'speed' 'valid_speeds'] + line_index=0 + with open(port_config_file) as data: + for line in data: + if line.startswith('#'): + if "name" in line: + titles = line.strip('#').split() + continue; + tokens = line.split() + + if len(tokens) < 6: + print("Unknown port_config.ini entry!\n") + continue + + port_names[line_index]=tokens[0] + port_lanes[line_index]=tokens[1] + port_alias[line_index]=tokens[2] + port_index[line_index]=tokens[3] + port_speed[line_index]=tokens[4] + port_valid_speed[line_index]=tokens[5] + line_index+=1 + + return (port_names, port_lanes, port_alias, port_index, port_speed, port_valid_speed) + +# Get platform name from ONIE +def get_onie_pname(): + cmd = "cat /host/machine.conf | grep onie_platform | cut -d '=' -f 2" + pin = subprocess.Popen(cmd, + shell=True, + close_fds=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + id = pin.communicate()[0] + id = id.strip() + return id + +if __name__ == '__main__': + + total_ports = 0 + + bcm_port_list_str = "BCM_PORT_LIST=" + sai_port_index_list_str = "SAI_PORT_INDEX_LIST=" + bcm_port_names_str = "BCM_PORT_NAMES=" + pdk_traffic_test_port_list_str = "PORT_CONFIG_INDEX_LIST=" + + (port_names, port_lanes, port_alias, port_index, port_speed, port_valid_speed) = get_port_config() + + for x in port_names: + number_of_lanes=port_lanes[x].count(",")+1 + lane_list=port_lanes[x].split(",") + highest_lane_num = max(lane_list) + + if (total_ports > 0): + bcm_port_list_str = bcm_port_list_str + "," + sai_port_index_list_str = sai_port_index_list_str + "," + + bcm_port_list_str = bcm_port_list_str + highest_lane_num + + sai_port_index_list_str = sai_port_index_list_str + "%d" % (total_ports + 1) + + total_ports +=1 + + filename = "/usr/lib/python2.7/dist-packages/sonic_pde_tests/data/platform/test-" + get_onie_pname() + "-config.json" + try: + with open ("/home/pde/test-config.json") as test_config: + port_dict = json.load(test_config) + except EnvironmentError as e: + try: + with open (filename) as test_config: + port_dict = json.load(test_config) + except Exception as e: + logging.error(e) + sys.exit() + except Exception as e: + logging.error(e) + sys.exit() + + total_test_ports=0 + list = port_dict["PLATFORM"]["TRAFFIC"]["port_pairs"] + for ports in list: + if (total_test_ports > 0): + pdk_traffic_test_port_list_str = pdk_traffic_test_port_list_str + "," + bcm_port_names_str = bcm_port_names_str + "," + + pdk_traffic_test_port_list_str = pdk_traffic_test_port_list_str + ports['src_front_portnum'] + "," + ports['dst_front_portnum'] + total_test_ports += 2 + + bcm_port_names_str = bcm_port_names_str + ports['src_logical_portnum'] + "," + ports['dst_logical_portnum'] + + print "####################################################################################" + print "#This file was auto generated" + print "#Please refer to the PDE SONiC Developers Guide for instructions" + print "#on how to modify contents according to your port configuration." + print "####################################################################################" + print "" + print "NUM_PORTS_IN_TEST=%d" % total_ports + print "NUM_PORTS_IN_TRAFFIC_TEST=%d" % total_test_ports + print "%s" % bcm_port_list_str + print "%s" % sai_port_index_list_str + print "%s" % bcm_port_names_str + print "%s" % pdk_traffic_test_port_list_str diff --git a/pde-test-host/pde-test-host/test_adapter_host.c b/pde-test-host/pde-test-host/test_adapter_host.c new file mode 100755 index 0000000..3f19d6d --- /dev/null +++ b/pde-test-host/pde-test-host/test_adapter_host.c @@ -0,0 +1,1192 @@ +/********************************************************************* + * + * (C) Copyright Broadcom Corporation 2013-2018 + * + **********************************************************************/ + +#include +#include +#include +#include "sai.h" +#include "saiUnitTest.h" +#include +#include "CUnit.h" +#include "Basic.h" +#include "Console.h" +#include "Automated.h" + +#define _REPEAT_COUNT 1 + +#define PRINT_LINK_STATUS +#define SET_SWITCH_MAC + +#define _SAI_API_ID_MIN SAI_API_UNSPECIFIED+1 +#define _SAI_API_ID_MAX SAI_API_BRIDGE + +//Custom attrobutes for as per internal design +#define SAI_SWITCH_ATTR_GET_SDK_BOOT_TIME SAI_SWITCH_ATTR_CUSTOM_RANGE_START +#define SAI_SWITCH_ATTR_SDK_SHUT_TIME_GET_FN SAI_SWITCH_ATTR_CUSTOM_RANGE_START+1 + +extern char *_brcm_sai_api_type_strings[]; + +#define _SAI_MAX_PORTS 256 + +#define NUM_TEST_PROFILES 4 +#define NUM_PROFILES 4 +#define MAX_PROFILE_KEY_SIZE 64 +#define MAX_PROFILE_VAL_SIZE 128 +#define _SAI_MAX_QUEUES 64 + +#define TRUE 1 +#define FALSE 0 + +#ifndef TEST_LOG_OFF +#define TEST_LOG(__fmt,__args...) \ + do { printf("%d: " __fmt, __LINE__ ,##__args); } while(0) +#else +#define TEST_LOG(...) +#endif + +#define CHECK_RV_RETURN(rv) if (rv!=SAI_STATUS_SUCCESS) \ + { fprintf(stderr, "Error in %s():%d rv=%d\n", __FUNCTION__, __LINE__, rv); return rv; } +#define CHECK_RV_STR_RETURN(str, rv) if (rv!=SAI_STATUS_SUCCESS) \ + { fprintf(stderr, "Error in %s > %s():%d rv=%d\n", str, __FUNCTION__, __LINE__, rv); return rv; } + +#define WAIT_FOR_EVENT(n) \ + { TEST_LOG("Wait %d secs for events to complete...\n", n); sleep(n); } + +#define _SAI_GET_OBJ_VAL(type, var) ((type)var) + +#define COUNTOF(ary) ((int) (sizeof (ary) / sizeof ((ary)[0]))) + +#define _BRCM_SAI_MAX_SCHEDULER_PROFILES 128 /* Max profiles */ + +#define CONFIG_STR_SIZE 64 +#define SYSTEM_CMD_STR_LEN 20 +#define NETIF_NAME_STR_LEN SYSTEM_CMD_STR_LEN + +//Struct to maintain lag,port and lag member info +typedef struct _lag_member_port_info{ + sai_object_id_t lag_obj; + sai_object_id_t lag_mbr_obj; + sai_object_id_t port_obj; + struct _lag_member_port_info *next; +}lag_member_port_info; + + +#define BRCM_SAI_CREATE_OBJ(type, value) ((((sai_object_id_t)type) << 32) | value) +#define BRCM_SAI_CREATE_OBJ_SUB(type, subtype, value) ((((sai_object_id_t)subtype) << 40) | \ + (((sai_object_id_t)type) << 32) | value) +#define BRCM_SAI_CREATE_OBJ_SUB_MAP(type, subtype, map, value) ((((sai_object_id_t)map) << 48) | \ + (((sai_object_id_t)subtype) << 40) | \ + (((sai_object_id_t)type) << 32) | value) +#define BRCM_SAI_GET_OBJ_TYPE(var) ((uint8_t)(var >> 32)) +#define BRCM_SAI_GET_OBJ_SUB_TYPE(var) ((uint8_t)(var >> 40)) +#define BRCM_SAI_GET_OBJ_MAP(var) ((uint16_t)(var >> 48)) +#define BRCM_SAI_GET_OBJ_VAL(type, var) ((type)var) +static char usage[] = +" Syntax : ./pde-test-host [-m|--cunit_mode] \n\r" +" eg: ./pde-test_host -m2 \n\r" +" Parameters : \n\r" +" -m|--cunit_mode : CUnit mode \n\r" +" cunit_mode - what mode to run the CUNIT tests \n\r" +" 0 - run in BASIC mode where summary is printed inline \n\r" +" 1 - run in AUTOMATED mode where summary is printed to files in /tmp \n\r" +" 2 - run in CONSOLE mode where you can run the tests interactively \n\r" +" default - 2 \n\r" +" Return : returns 0 \n\r"; + +/* +################################################################################ +# Global state # +################################################################################ +*/ +/* Declare API pointers and table */ +sai_switch_api_t *sai_switch_apis; +sai_port_api_t *sai_port_apis; +sai_vlan_api_t *sai_vlan_apis; +sai_fdb_api_t *sai_fdb_apis; +sai_virtual_router_api_t *sai_router_apis; +sai_router_interface_api_t *sai_router_intf_apis; +sai_neighbor_api_t *sai_neighbor_apis; +sai_next_hop_api_t *sai_next_hop_apis; +sai_next_hop_group_api_t *sai_next_hop_grp_apis; +sai_route_api_t *sai_route_apis; +sai_hostif_api_t *sai_hostif_apis; +sai_acl_api_t *sai_acl_apis; +sai_policer_api_t *sai_policer_apis; +sai_qos_map_api_t *sai_qos_map_apis; +sai_queue_api_t *sai_qos_queue_apis; +sai_wred_api_t *sai_wred_apis; +sai_scheduler_api_t *sai_qos_scheduler_apis; +sai_scheduler_group_api_t *sai_qos_sched_group_apis; +sai_buffer_api_t *sai_buffer_apis; +sai_lag_api_t *sai_lag_apis; +sai_tunnel_api_t *sai_tunnel_apis; +sai_mirror_api_t *sai_mirror_apis; +sai_udf_api_t *sai_udf_apis; +sai_hash_api_t *sai_hash_apis; +sai_bridge_api_t *sai_bridge_apis; + +static void *adapter_apis[_SAI_API_ID_MAX+1]; + +#define SAI_BUFFER_PROFILE_ATTR_BRCM_CUSTOM_USE_QGROUP_MIN (SAI_BUFFER_PROFILE_ATTR_CUSTOM_RANGE_START) + +typedef struct _profile_kvp_s { + char k[MAX_PROFILE_KEY_SIZE]; + char v[MAX_PROFILE_VAL_SIZE]; +} profile_kvp_t; + +static const profile_kvp_t profile_kvp_table[NUM_TEST_PROFILES][NUM_PROFILES] = { + { + { SAI_KEY_INIT_CONFIG_FILE, "/tmp/brcm_sai_config.bcm" }, + { SAI_KEY_BOOT_TYPE, "0" }, + { SAI_KEY_WARM_BOOT_READ_FILE, "/tmp/brcm_sai.wb" }, +#ifdef WB_PERF + { SAI_KEY_NUM_ECMP_MEMBERS, "64" } +#else + { SAI_KEY_NUM_ECMP_MEMBERS, "32" } +#endif + }, + { + { SAI_KEY_INIT_CONFIG_FILE, "/tmp/brcm_sai_config.bcm" }, + { SAI_KEY_BOOT_TYPE, "1" }, + { SAI_KEY_WARM_BOOT_READ_FILE, "/tmp/brcm_sai.wb" }, +#ifdef WB_PERF + { SAI_KEY_NUM_ECMP_MEMBERS, "64" } +#else + { SAI_KEY_NUM_ECMP_MEMBERS, "32" } +#endif + }, + { + { SAI_KEY_INIT_CONFIG_FILE, "/tmp/brcm_sai_config.bcm" }, + { SAI_KEY_BOOT_TYPE, "2" }, + { SAI_KEY_WARM_BOOT_READ_FILE, "/tmp/brcm_sai.wb" }, +#ifdef WB_PERF + { SAI_KEY_NUM_ECMP_MEMBERS, "32" } +#else + { SAI_KEY_NUM_ECMP_MEMBERS, "32" } +#endif + }, + { + { "KEY1_0", "VALUE1_0" }, + { "KEY1_1", "VALUE1_1" }, + { "KEY1_2", "VALUE1_2" } + } +}; + +static int wb = 0; /* Warm boot */ +static int queue_count = 0; +int pfc_deadlock_detect_event = 0, pfc_deadlock_recover_event = 0; +sai_uint32_t port_loopback_mode; +static struct timeval begin, end; +/***************************Persistent State***********************************/ +static sai_object_id_t switch_id = 0; +static sai_object_id_t dot1q_bridge = 0; +static sai_object_id_t cpu_port = 0; +static sai_object_id_t ports[_SAI_MAX_PORTS]; +static sai_object_list_t port_list = { _SAI_MAX_PORTS, ports }; +static sai_object_id_t b_ports[_SAI_MAX_PORTS]; +static sai_object_list_t b_port_list = { _SAI_MAX_PORTS, b_ports }; +static sai_object_id_t vlan_objs[10]; +static sai_object_id_t lag0, lag1; +static sai_object_id_t bp_lag0, bp_lag1; +static sai_object_id_t vr_id[3] = { 0 }; +static sai_object_id_t rif_id[12] = { 0 }; +static sai_object_id_t nh_id[7] = { -1, -1, -1, -1, -1, -1, -1 }; +static sai_object_id_t nh_gid[3] = { -1, -1, -1 }; +static sai_object_id_t t_nh_g_membr[2] = { 0, 0 }; +static sai_object_id_t nh_g_membr[6] = { 0, 0, 0, 0, 0, 0 }; +static sai_object_id_t hif_id[10] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; +static sai_object_id_t policer_id0 = -1; +static sai_object_id_t policer_id[3] = { -1, -1, -1 }; +static sai_object_id_t acl_counter_id = -1; +sai_object_id_t qid[_SAI_MAX_PORTS][_SAI_MAX_QUEUES]; +static sai_object_id_t acl_entry_id, acl_entry_id2; +static sai_object_id_t scheduler_id1, scheduler_id2, scheduler_id3, + scheduler_id4, scheduler_id5, scheduler_id6, + scheduler_id7; +static sai_object_id_t sched_grp[_SAI_MAX_PORTS][3][10]; /* port, level, nodes */ +static sai_object_id_t lm[5]; +static sai_object_id_t acl_range; +uint32_t sdk_shut_time;//to measure sdk shut time from callback +lag_member_port_info *root_node = NULL;//Dont make static as we need it in CUnit. + +static sai_attribute_t lag_mbr_attr[] = { + {SAI_LAG_MEMBER_ATTR_LAG_ID}, + {SAI_LAG_MEMBER_ATTR_PORT_ID}, +}; + +/* test config file params */ +int num_ports_in_test; +int num_ports_in_traffic_test; +int bcm_port_list[_SAI_MAX_PORTS]; +int sai_port_index_list[_SAI_MAX_PORTS]; +int pde_traffic_test_port_list[_SAI_MAX_PORTS]; +char* bcm_port_list_names[_SAI_MAX_PORTS]; +char* mmu_init_config; +int bcm_loopback_port_list[_SAI_MAX_PORTS]; +int capture_enable;//Decides whether capturing needs to be enable in CUnits +int warmboot_enable;//Decides whether warmshut/warmboot to be run in CUnits +int sdk_pfc_dl_recovery, collect_syslog; + + +extern char* saiUnitGetBcmPortName(int index); +/* Note: Any data added in the above 'persistent state section will need to be + * stored and loaded in the below routines in the same order: + */ +/******************************************************************************/ + +#define _TEST_DATA_STORE(data) fprintf(fp, "%lx\n", (long unsigned int)data); +#define _TEST_DATA_STORE_1(data) \ + for (i=0; ivalue.u32 != act_attr->value.u32) + { + TEST_LOG("--Set attrib failed.\n"); + } + else + { + TEST_LOG("--Set attrib passed.\n"); + } +} + +void +_test_verify_print_num_attributes(char *prepend, int num, + const sai_attribute_t *act_attr, + sai_attribute_t *attr) +{ + if (attr->value.u32 != act_attr->value.u32) + { + TEST_LOG("--Set attrib failed for %d.\n", num); + } + else + { + TEST_LOG("--Set attrib passed for %d.\n", num); + } +} + +sai_object_id_t +_get_cpu_port_object() +{ + return cpu_port; +} + +int +_get_port_count() +{ + return port_list.count; +} + +sai_object_id_t +_get_port_object(int index) +{ + if (index > port_list.count) + { + return (sai_object_id_t)NULL; + } + return port_list.list[index]; +} + +sai_object_id_t +_get_bridge_port_object(int index) +{ + if (index > b_port_list.count) + { + return (sai_object_id_t)NULL; + } + return b_port_list.list[index]; +} + +int parse_values_int(char* temp, int* arr) +{ + char* token; + int i=0; + if (isdigit(*temp) && strstr(temp, ",") != 0) + { + /* Comma sep values */ + while (1) + { + token = strtok(temp, ","); + if (token != NULL) + { + arr[i++] = atoi(token); + temp = NULL; + } + else break; + } + } + else + /* Single value */ + { + while (1) + { + token = strtok(temp, "\n"); + if (token != NULL) + { + arr[i++] = atoi(token); + temp =NULL; + } + else break; + } + } + return 0; +} + +int parse_values_str(char* temp, char** arr) +{ + char* token; + int i=0; + if (strstr(temp, ",") != 0) + { + while (1) + { + token = strtok(temp, ",\n");//multiple delimiters to avoid /n append to last token + if (token != NULL) + { + arr[i] = (char*)malloc(sizeof(token)); + memset(arr[i],'\0',sizeof(token)); + strcpy(arr[i++], token); + temp =NULL; + } + else break; + } + } + else + { + while (1) + { + token = strtok(temp, "\n"); + if (token != NULL) + { + arr[i] = (char*)malloc(strlen(token)+1); + memset(arr[i],'\0',strlen(token)+1); + strcpy(arr[i++], token); + temp =NULL; + } + else break; + } + } + return 0; +} + +/* Expects a line with \n */ +int parse_line(char* lineptr, int len) +{ + char* temp = lineptr; + if (!temp || (len <= 1)) return 0; + + while (isspace(*temp)) {temp++;} + + // Ignore lines with comments + if (*temp == '#') return 0; + + // Look for a known word + /* All words to be parsed from file */ + if ((strstr(lineptr, "BCM_PORT_LIST") == 0) || \ + (strstr(lineptr, "NUM_PORTS_IN_TEST") == 0) || \ + (strstr(lineptr, "SAI_PORT_INDEX_LIST") == 0) || \ + (strstr(lineptr, "BCM_PORT_LIST_NAMES") == 0)|| \ + (strstr(lineptr, "BCM_PORT_NAMES") == 0)|| \ + (strstr(lineptr, "MMU_INIT_CONFIG") == 0) || \ + (strstr(lineptr, "PORT_CONFIG_INDEX_LIST") == 0) || \ + (strstr(lineptr, "BCM_LOOPBACK_PORTS_LIST") == 0)) + { + temp = strchr(lineptr, '='); + if (temp == NULL) + return 0; // bad string? + + if (*temp == '=') + { + int i = 0; + char* token; + temp++; + + while(isspace(*temp)) { + temp++; + } + if (strstr(lineptr, "BCM_PORT_LIST") != 0) + { + parse_values_int(temp, bcm_port_list); + } + if (strstr(lineptr, "NUM_PORTS_IN_TRAFFIC_TEST") != 0) + { + parse_values_int(temp, &num_ports_in_traffic_test); + } + if (strstr(lineptr, "NUM_PORTS_IN_TEST") != 0) + { + parse_values_int(temp, &num_ports_in_test); + } + if (strstr(lineptr, "SAI_PORT_INDEX_LIST") != 0) + { + parse_values_int(temp, sai_port_index_list); + } + if (strstr(lineptr, "BCM_PORT_NAMES") != 0) + { + parse_values_str(temp, bcm_port_list_names); + } + if (strstr(lineptr, "MMU_INIT_CONFIG") != 0) + { + parse_values_str(temp, &mmu_init_config); + } + if (strstr(lineptr, "BCM_LOOPBACK_PORTS_LIST") != 0) + { + parse_values_int(temp, bcm_loopback_port_list); + } + if (strstr(lineptr, "PORT_CONFIG_INDEX_LIST") != 0) + { + parse_values_int(temp, pde_traffic_test_port_list); + } + } + } + return 0; +} + + + + +/* +################################################################################ +# Services and events # +################################################################################ +*/ + +/* +* Get variable value given its name +*/ +const char* +profile_get_value(_In_ sai_switch_profile_id_t profile_id, + _In_ const char* variable) +{ + int i; + + for (i = 0; i= NUM_TEST_PROFILES) { + return -1; + } + if (NULL == *variable) + { + /*TEST_LOG("KVP reset\n");*/ + i[profile_id] = 0; + return 0; + } + if (variable) + { + /*TEST_LOG("KVP profile %d offset %d key: %s\n", profile_id, i[profile_id], + profile_kvp_table[profile_id][i[profile_id]].k);*/ + *variable = profile_kvp_table[profile_id][i[profile_id]].k; + } + if (value) + { + *value = profile_kvp_table[profile_id][i[profile_id]].v; + } + if ((NUM_PROFILES-1) == i[profile_id]) + { + return -1; + } + i[profile_id]++; + + return 0; +} + +/* +* Routine Description: +* Switch shutdown request callback. +* Adapter DLL may request a shutdown due to an unrecoverable failure +* or a maintenance operation +* +* Arguments: +* None +* +* Return Values: +* None +*/ +void +sai_switch_shutdown_request(void) +{ + TEST_LOG("----Host received switch shutdown request event\n"); +} + +/* +* Routine Description: +* Switch oper state change notification +* +* Arguments: +* [in] switch_oper_status - new switch oper state +* +* Return Values: +* None +*/ +void +sai_switch_state_change_notification(_In_ sai_object_id_t switch_id, + _In_ sai_switch_oper_status_t switch_oper_status) +{ + TEST_LOG("----Host received switch status event: %d from switch: 0x%lx\n", + switch_oper_status, switch_id); +} + +/* +* Routine Description: +* PFC event notifications +* +* Arguments: +* [in] count - number of notifications +* [in] data - pointer to pfc event notification data +* +* Return Values: +* None +*/ +void sai_queue_pfc_deadlock_notification(_In_ uint32_t count, + _In_ sai_queue_deadlock_notification_data_t *data) +{ + switch(data->event) + { + case SAI_QUEUE_PFC_DEADLOCK_EVENT_TYPE_DETECTED: + printf("Deadlock detected on queue id %d count number is %d\n",_SAI_GET_OBJ_VAL(int, data->queue_id), count); + pfc_deadlock_detect_event++; + break; + case SAI_QUEUE_PFC_DEADLOCK_EVENT_TYPE_RECOVERED: + printf("Deadlock recovered on queue id %d count number is %d\n",_SAI_GET_OBJ_VAL(int, data->queue_id), count); + pfc_deadlock_recover_event++; + break; + default : + printf("Unknown event occured in PFC callback\n"); + break; + } + if(!sdk_pfc_dl_recovery){ + data->app_managed_recovery = TRUE;//Should not return true if we want to have sdk based pfc dl recovery + } +} + +/* +* Routine Description: +* FDB notifications +* +* Arguments: +* [in] count - number of notifications +* [in] data - pointer to fdb event notification data array +* +* Return Values: +* None +*/ +void +sai_fdb_event_notification(_In_ uint32_t count, + _In_ sai_fdb_event_notification_data_t *data) +{ +#ifdef PRINT_L2_UPDATES + uint8_t *mac = data->fdb_entry.mac_address; + TEST_LOG("----Host received FDB event type: "); + switch (data->event_type) + { + case SAI_FDB_EVENT_LEARNED: TEST_LOG("LEARN vid=%d mac=%x:%x:%x:%x:%x:%x ", + _SAI_GET_OBJ_VAL(int, data->fdb_entry.bv_id), + mac[0], mac[1],mac[2], mac[3], mac[4], mac[5]); + break; + case SAI_FDB_EVENT_AGED: TEST_LOG("AGE vid=%d mac=%x:%x:%x:%x:%x:%x ", + _SAI_GET_OBJ_VAL(int, data->fdb_entry.bv_id), + mac[0], mac[1],mac[2], mac[3], mac[4], mac[5]); + break; + case SAI_FDB_EVENT_FLUSHED: TEST_LOG("FLUSH\n"); + break; + default: TEST_LOG("UNKNOWN\n"); + break; + } + if (data->attr_count && (SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID == data->attr[0].id)) + { + if (SAI_OBJECT_TYPE_LAG == sai_object_type_query(data->attr[0].value.oid)) + { + TEST_LOG("lag:%d\n", _SAI_GET_OBJ_VAL(int, data->attr[0].value.oid)); + } + else + { + TEST_LOG("port:%d\n", _SAI_GET_OBJ_VAL(int, data->attr[0].value.oid)); + } + } + else + { + TEST_LOG("\n"); + } +#endif +} + +/* +* Routine Description: +* Port state change notification +* Passed as a parameter into sai_initialize_switch() +* +* Arguments: +* [in] count - number of notifications +* [in] data - array of port operational status +* +* Return Values: +* None +*/ +//INFO must be reentrant routine +void +sai_port_state_change_notification(_In_ uint32_t count, + _In_ sai_port_oper_status_notification_t *data) +{ +#ifdef PRINT_LINK_STATUS + TEST_LOG("----Host received port link status event on port %3d: %s\n", + _SAI_GET_OBJ_VAL(int, data->port_id), + (SAI_PORT_OPER_STATUS_UP == data->port_state) ? " UP" : "DOWN"); +#endif + lag_member_port_info *lag_mbr_list; + lag_mbr_list = root_node; + while (lag_mbr_list != NULL){ + if (lag_mbr_list->port_obj == data->port_id){ + if (data->port_state == SAI_PORT_OPER_STATUS_UP){ + //Add ports to lag + lag_mbr_attr[0].value.oid = lag_mbr_list->lag_obj; + lag_mbr_attr[1].value.oid = data->port_id; + CU_ASSERT(SAI_STATUS_SUCCESS == + sai_lag_apis->create_lag_member(&lag_mbr_list->lag_mbr_obj, + 0, + COUNTOF(lag_mbr_attr), + lag_mbr_attr)); + } + else{ + //Remove ports from lag + CU_ASSERT(SAI_STATUS_SUCCESS == + sai_lag_apis->remove_lag_member(lag_mbr_list->lag_mbr_obj)); + } + } + //possibilty that the port may belong to other lags also so traverse complete list. + lag_mbr_list = lag_mbr_list->next; + } +} + +/* +* Routine Description: +* Callback fn which returns sdk shutdown time. +* Passed as a parameter into create_switch() +* +* Arguments: +* [in] unit - Device unit number(nothing to do with SAI now better replace with switch_id) +* [in] time_sec - time take to do shutdown +* +* Return Values: +* None +*/ + +void sai_sdk_shutdown_time_get(int unit, unsigned int time_sec){ + sdk_shut_time = time_sec;//sdk_shut_time is global and externed to use in CUnit + TEST_LOG("\nSDK took %d secs to shut.", sdk_shut_time); +} + +/* +################################################################################ +# Test Init API # +################################################################################ +*/ + +static const sai_service_method_table_t test_services = { + .profile_get_value = profile_get_value, + .profile_get_next_value = profile_get_next_value +}; + +sai_status_t +test_adapter_api_init(void) +{ + sai_status_t rv; + + rv = sai_api_initialize(0, &test_services); + return rv; +} + +sai_status_t +test_query_adapter_methods(sai_api_t api) +{ + sai_status_t rv; + + rv = sai_api_query(api, &adapter_apis[api]); + switch(api) + { + case SAI_API_SWITCH: sai_switch_apis = (sai_switch_api_t*)adapter_apis[api]; + break; + case SAI_API_PORT: sai_port_apis = (sai_port_api_t*)adapter_apis[api]; + break; + case SAI_API_FDB: sai_fdb_apis = (sai_fdb_api_t*)adapter_apis[api]; + break; + case SAI_API_VIRTUAL_ROUTER: sai_router_apis = (sai_virtual_router_api_t*)adapter_apis[api]; + break; + case SAI_API_ROUTER_INTERFACE: sai_router_intf_apis = (sai_router_interface_api_t*)adapter_apis[api]; + break; + case SAI_API_NEIGHBOR: sai_neighbor_apis = (sai_neighbor_api_t*)adapter_apis[api]; + break; + case SAI_API_ROUTE: sai_route_apis = (sai_route_api_t*)adapter_apis[api]; + break; + case SAI_API_NEXT_HOP: sai_next_hop_apis = (sai_next_hop_api_t*)adapter_apis[api]; + break; + case SAI_API_VLAN: sai_vlan_apis = (sai_vlan_api_t*)adapter_apis[api]; + break; + case SAI_API_NEXT_HOP_GROUP: sai_next_hop_grp_apis = (sai_next_hop_group_api_t*)adapter_apis[api]; + break; + case SAI_API_POLICER: sai_policer_apis = (sai_policer_api_t*)adapter_apis[api]; + break; + case SAI_API_ACL: sai_acl_apis = (sai_acl_api_t*)adapter_apis[api]; + break; + case SAI_API_HOSTIF: sai_hostif_apis = (sai_hostif_api_t*)adapter_apis[api]; + break; + case SAI_API_WRED: sai_wred_apis = (sai_wred_api_t*)adapter_apis[api]; + break; + case SAI_API_QOS_MAP: sai_qos_map_apis = (sai_qos_map_api_t*)adapter_apis[api]; + break; + case SAI_API_QUEUE: sai_qos_queue_apis = (sai_queue_api_t*)adapter_apis[api]; + break; + case SAI_API_SCHEDULER: sai_qos_scheduler_apis = (sai_scheduler_api_t*)adapter_apis[api]; + break; + case SAI_API_SCHEDULER_GROUP: sai_qos_sched_group_apis = (sai_scheduler_group_api_t*)adapter_apis[api]; + break; + case SAI_API_BUFFER: sai_buffer_apis = (sai_buffer_api_t*)adapter_apis[api]; + break; + case SAI_API_LAG: sai_lag_apis = (sai_lag_api_t*)adapter_apis[api]; + break; + case SAI_API_TUNNEL: sai_tunnel_apis = (sai_tunnel_api_t*)adapter_apis[api]; + break; + case SAI_API_MIRROR: sai_mirror_apis = (sai_mirror_api_t*)adapter_apis[api]; + break; + case SAI_API_UDF: sai_udf_apis = (sai_udf_api_t*)adapter_apis[api]; + break; + case SAI_API_HASH: sai_hash_apis = (sai_hash_api_t*)adapter_apis[api]; + break; + case SAI_API_BRIDGE: sai_bridge_apis = (sai_bridge_api_t*)adapter_apis[api]; + break; + default: + return 0; + } + return rv; +} + +sai_status_t +test_query_all_adapter_methods() +{ + sai_status_t rv; + sai_api_t api; + + for (api=_SAI_API_ID_MIN; api<=_SAI_API_ID_MAX; api++) + { + rv = test_query_adapter_methods(api); + CHECK_RV_STR_RETURN("query adpter method", rv); + } +} + +/* +################################################################################ +# Set log levels # +################################################################################ +*/ +sai_status_t +test_set_all_log_levels(sai_log_level_t level) +{ + sai_status_t rv; + sai_api_t api; + + for (api=_SAI_API_ID_MIN; api<=_SAI_API_ID_MAX; api++) + { + rv = sai_log_set(api, level); + if (rv!=SAI_STATUS_SUCCESS) + { + return rv; + } + TEST_LOG("API %s log level set to %d\n", _brcm_sai_api_type_strings[api], level); + } + return SAI_STATUS_SUCCESS; +} + +/* +################################################################################ +# Test De-Init API # +################################################################################ +*/ +sai_status_t +test_adapter_api_deinit() +{ + sai_status_t rv = SAI_STATUS_FAILURE; + + rv = sai_api_uninitialize(); + return rv; +} + +/* +################################################################################ +# Test Init switch # +################################################################################ +*/ +sai_status_t +test_adapter_switch_create() +{ + sai_status_t rv = SAI_STATUS_FAILURE; + + const sai_attribute_t attr_set0[] = { + { SAI_SWITCH_ATTR_INIT_SWITCH, .value.booldata=TRUE }, + { SAI_SWITCH_ATTR_SWITCH_PROFILE_ID, .value.u32=0 }, + { SAI_SWITCH_ATTR_SWITCH_STATE_CHANGE_NOTIFY, .value.ptr = sai_switch_state_change_notification }, + { SAI_SWITCH_ATTR_FDB_EVENT_NOTIFY, .value.ptr = sai_fdb_event_notification }, + { SAI_SWITCH_ATTR_PORT_STATE_CHANGE_NOTIFY, .value.ptr = sai_port_state_change_notification }, + { SAI_SWITCH_ATTR_QUEUE_PFC_DEADLOCK_NOTIFY, .value.ptr = sai_queue_pfc_deadlock_notification }, + { SAI_SWITCH_ATTR_SDK_SHUT_TIME_GET_FN, .value.ptr = sai_sdk_shutdown_time_get} +#ifndef SET_SWITCH_MAC + , + { SAI_SWITCH_ATTR_SRC_MAC_ADDRESS, + .value.mac = { 0x00, 0x05, 0x06, 0x08, 0x05, 0x00 } + } +#endif + }; + + const sai_attribute_t attr_set1[] = { + { SAI_SWITCH_ATTR_INIT_SWITCH, .value.booldata=TRUE }, + { SAI_SWITCH_ATTR_SWITCH_PROFILE_ID, .value.u32=1 }, + { SAI_SWITCH_ATTR_SWITCH_STATE_CHANGE_NOTIFY, .value.ptr = sai_switch_state_change_notification }, + { SAI_SWITCH_ATTR_FDB_EVENT_NOTIFY, .value.ptr = sai_fdb_event_notification }, + { SAI_SWITCH_ATTR_PORT_STATE_CHANGE_NOTIFY, .value.ptr = sai_port_state_change_notification }, + { SAI_SWITCH_ATTR_QUEUE_PFC_DEADLOCK_NOTIFY, .value.ptr = sai_queue_pfc_deadlock_notification }, + { SAI_SWITCH_ATTR_SDK_SHUT_TIME_GET_FN, .value.ptr = sai_sdk_shutdown_time_get} + }; + + if (NULL != sai_switch_apis->create_switch) + { + rv = sai_switch_apis->create_switch(&switch_id, COUNTOF(attr_set0), + wb ? attr_set1 : attr_set0); + if (SAI_STATUS_SUCCESS == rv) + { + TEST_LOG("Created switch: 0x%lx.\n", switch_id); + } + } + return rv; +} + +/* +################################################################################ +# Test Shutdown switch # +################################################################################ +*/ +sai_status_t +test_adapter_switch_shutdown(bool ws) +{ + sai_status_t rv; + + sai_attribute_t switch_attr[] = + { + { SAI_SWITCH_ATTR_RESTART_WARM } + }; + + /* brcm_sai_shutdown_switch */ + if (NULL != sai_switch_apis->set_switch_attribute) + { + switch_attr[0].value.booldata = ws; /* WB hint */ + gettimeofday(&begin, NULL); + rv = sai_switch_apis->set_switch_attribute(switch_id, switch_attr); + if (SAI_STATUS_SUCCESS != rv) + { + TEST_LOG("set_switch_attribute failed with error %d\n", rv); + return rv; + } + } + rv = sai_switch_apis->remove_switch(switch_id); + gettimeofday(&end, NULL); +#ifdef WB_PERF + TEST_LOG("\nSAI took %d secs to shut.",(int)(end.tv_sec - begin.tv_sec)); +#endif + return rv; +} + + +static void ds() +{ + TEST_LOG("Hit enter to get drivshell prompt..\n"); + sai_driver_shell(); +} + +/********************************************************************* + * \brief Main function for sample test adapter host + * + * \param argc, argv commands line arguments + * + * \return 0 + ********************************************************************/ +int main(int argc, char *argv[]) +{ + int i; + bool ws = FALSE; /* Warm shut - don't cleanup */ + sai_status_t rv; + int cunit_cfg = 1; + int cunit_mode = 2; + capture_enable = 0; + warmboot_enable = 0; + size_t len = 0, read = 0; + char *lineptr; + + static struct option long_options[] = { + {"cunit_mode", optional_argument, NULL, 'm'}, + {"help", no_argument, NULL, 'h'}, + { NULL, 0, NULL, 0 } + }; + char opt; + while((opt = getopt_long(argc, argv, ":m::h", long_options, NULL)) != -1){ + switch(opt){ + case 'm': + if(optarg != NULL) + cunit_mode = atoi(optarg); + else + cunit_mode = 0; + break; + case 'h': + case ':': + case '?': + default : + printf("%s\n\r", usage); + exit(-1); + } + } + + FILE *fp = fopen ("/tmp/test_config.ini", "r"); + if (fp == NULL) { + TEST_LOG("Please make /tmp/test_config.ini is present\n"); + return -1; + } + while(read = getline(&lineptr, &len, fp) != -1) { + parse_line(lineptr, len); + // free and reset lineptr + if (lineptr) + free(lineptr); + lineptr = 0; + } + + rv = test_adapter_api_init(); + rv = test_query_all_adapter_methods(); + rv = test_adapter_switch_create(); + + for (len=0;len < num_ports_in_test; len++) + { + if ( sai_port_index_list[len] == 0) + { + sai_port_index_list[len] = saiUnitSaiIndexGet(bcm_port_list[len]); + + if (sai_port_index_list[len] == -1) + { + TEST_LOG("Could not convert BCM %d to SAI port\n", + bcm_port_list[len]); + } + else + { + TEST_LOG("BCM %d, SAI Obj Id %d, Name %s\n", + bcm_port_list[len], sai_port_index_list[len], + bcm_port_list_names[len]); + } + } + } + + saiUnitTestsRun(cunit_mode, cunit_cfg, SAI_TEST_ID_PDE); + rv = test_adapter_switch_shutdown(ws); + CHECK_RV_STR_RETURN("switch shutdown", rv); + rv = test_adapter_api_deinit(); + CHECK_RV_STR_RETURN("api deinit", rv); + rv = test_set_all_log_levels(SAI_LOG_LEVEL_ERROR); + CHECK_RV_STR_RETURN("all log levels set to warn", rv); + + if (ws) + { + rv = _test_ws_save(); + CHECK_RV_STR_RETURN("test objects store", rv); + } + TEST_LOG("Test adapter complete.\n"); + + return 0; +} + + + + diff --git a/pde-test-host/pde-test-host/unittests/saiSonicPde.c b/pde-test-host/pde-test-host/unittests/saiSonicPde.c new file mode 100644 index 0000000..4b715eb --- /dev/null +++ b/pde-test-host/pde-test-host/unittests/saiSonicPde.c @@ -0,0 +1,511 @@ +/********************************************************************* + * + * Broadcom Proprietary and Confidential. (C) Copyright 2016-2018 Broadcom. + * All rights reserved. + * + ********************************************************************** + * + * @filename saiSonicPde.c + * + * @purpose This file contains the unit tests for SONiC PDE + * + * @component unit test + * + * @comments + * + * @create + * + * @author + * + * @end + * + **********************************************************************/ + +#include "saiUnitUtil.h" + +#ifndef TEST_LOG_OFF +#define TEST_LOG(__fmt,__args...) \ + do { printf("%d: " __fmt, __LINE__ ,##__args); } while(0) +#else +#define TEST_LOG(...) +#endif + + +CU_pSuite pSonicPdeSuite; +#define MAX_MTU 256 +#define TRAFFIC_FRAME_COUNT 5000 + +/* Frmaes to be sent to host 2.2.2.1 as dest ip */ +static sai_status_t saiUnitSendFramesToHost(char *port, int numFrames) +{ + sai_status_t rv = SAI_STATUS_SUCCESS; + char frameData[MAX_FRAME_SIZE]; + saiHideConsoleOutput(); + /* input packet */ + sprintf(frameData, "tx %d pbm=%s data=\'00445555666600000000000208004500002E0000000040FF73CD01010101" + "02020201000102030405060708090A0B0C0D0E0F10111213141516171819E240029C\'", numFrames, port); + rv = sai_driver_process_command(frameData); + sleep(3); + saiShowConsoleOutput(); + return rv; +} + +/* Below is example of port_config.ini line + +# name lanes alias index speed +Ethernet0 65,66,67,68 Eth1 1 100000 + +*/ + +typedef struct _sai_port_map_entry { + sai_object_id_t port_id; + uint32_t total_lanes; + uint32_t lane_list[4]; + uint32_t speed; +} sai_port_map_entry; + +typedef struct _sai_port_map { + int total_ports; + sai_port_map_entry port_list[_SAI_MAX_PORTS]; + +} sai_port_map; + +sai_port_map pdeTestSaiPortMap; + + +typedef struct _port_config_map_entry { + char name[20]; + uint32_t total_lanes; + uint32_t lane_list[4]; + uint32_t speed; + int index; +} port_config_map_entry; + +typedef struct _port_config_map { + int total_ports; + port_config_map_entry port_list[_SAI_MAX_PORTS]; + +} port_config_map; + +port_config_map pdeTestPortConfigMap; + + +int saiSonicPdeLoadPortConfig() +{ + char name[20]; + char lanes[20]; + char alias[20]; + char hwsku[255]; + char platform[255]; + int index; + int speed; + int total_ports = 0; + char filepath[255]; + + size_t len = 0, num_read = 0; + char *lineptr; + FILE *fp; + + sprintf(filepath, "/tmp/port_config.ini", platform, hwsku); + + fp = fopen(filepath, "r"); + if (fp == NULL) + { + printf("FAIL: Unable to open file %s\n", filepath); + TEST_LOG("Please ensure that port_config.ini is present in cwd\n"); + return -1; + } + else + { + printf("\nPASS: Able to open %s \n", filepath); + } + + while (num_read = getline(&lineptr, &len, fp) != -1) + { + if (*lineptr == '#') + { + continue; + } + else + { + if (5 != sscanf(lineptr, "%s %s %s %d %d", name, lanes, alias, &index, &speed)) + { + printf("FAIL: Invalid line %s in port_config.ini, please check syntax!", lineptr); + } + else + { + strcpy(pdeTestPortConfigMap.port_list[total_ports].name, name); + pdeTestPortConfigMap.port_list[total_ports].speed = speed; + pdeTestPortConfigMap.port_list[total_ports].index = index; + pdeTestPortConfigMap.port_list[total_ports].total_lanes = sscanf(lanes, "%d,%d,%d,%d", + &pdeTestPortConfigMap.port_list[total_ports].lane_list[0], + &pdeTestPortConfigMap.port_list[total_ports].lane_list[1], + &pdeTestPortConfigMap.port_list[total_ports].lane_list[2], + &pdeTestPortConfigMap.port_list[total_ports].lane_list[3]); + + total_ports++; + } + } + } + pdeTestPortConfigMap.total_ports = total_ports; + + return total_ports; +} + +int saiSonicPdeLoadSaiPortMap() +{ + int max_ports; + int i, j; + uint32_t lane_list[4]; + sai_status_t rv = 0; + + sai_attribute_t attr_get[_SAI_MAX_PORTS] = + { + { SAI_PORT_ATTR_HW_LANE_LIST, .value.u32list.list = &lane_list[0] } + }; + + sai_attribute_t attr_get_port_speed[_SAI_MAX_PORTS] = + { + { SAI_PORT_ATTR_SPEED, .value.u32 = 0x00 } + }; + + CU_ASSERT(SAI_STATUS_SUCCESS == saiUnitGetSwitchPortCount(&max_ports)); + + pdeTestSaiPortMap.total_ports = max_ports; + + /* For each port, get the lane count and values as well as configured speed of port*/ + for (i = 0; i < max_ports; i++) + { + pdeTestSaiPortMap.port_list[i].port_id = saiUnitGetPortObject(i); + + attr_get[0].value.u32list.count = 4; + CU_ASSERT(SAI_STATUS_SUCCESS == + (rv = saiUnitGetPortAttribute(pdeTestSaiPortMap.port_list[i].port_id, attr_get))); + if (SAI_STATUS_SUCCESS == rv) + { + if (attr_get[0].value.u32list.count) + { + pdeTestSaiPortMap.port_list[i].total_lanes = attr_get[0].value.u32list.count; + for (j = 0; j < attr_get[0].value.u32list.count; j++) + { + pdeTestSaiPortMap.port_list[i].lane_list[j] = attr_get[0].value.u32list.list[j]; + } + } + } + + CU_ASSERT(SAI_STATUS_SUCCESS == + (rv = saiUnitGetPortAttribute(pdeTestSaiPortMap.port_list[i].port_id, attr_get_port_speed))); + if (SAI_STATUS_SUCCESS == rv) + { + if (attr_get_port_speed[0].value.u32) + { + pdeTestSaiPortMap.port_list[i].speed = attr_get_port_speed[0].value.u32; + } + } + + } + + return max_ports; +} + +int saiGetPortIdfromPortConfig(int index, sai_object_id_t *port_obj) +{ + int i, j; + int found = 0; + + for (i = 0; i < pdeTestSaiPortMap.total_ports; i++) + { + if (pdeTestSaiPortMap.port_list[i].total_lanes == pdeTestPortConfigMap.port_list[index].total_lanes) + { + for (j = 0; j < pdeTestPortConfigMap.port_list[index].total_lanes; j++) + { + if (pdeTestPortConfigMap.port_list[index].lane_list[j] != pdeTestSaiPortMap.port_list[i].lane_list[j]) + { + break; + } + } + } + + if (j == pdeTestPortConfigMap.port_list[index].total_lanes) + { + *port_obj = pdeTestSaiPortMap.port_list[i].port_id; + found = 1; + } + } + + return found; +} + +void dumpPortTables(int i) +{ + int j; + + printf("Port ID: 0x%016lx Speed: %d Total Lanes: %d Lanes: ", pdeTestSaiPortMap.port_list[i].port_id, + pdeTestSaiPortMap.port_list[i].speed, pdeTestSaiPortMap.port_list[i].total_lanes); + for (j = 0; j < pdeTestSaiPortMap.port_list[i].total_lanes; j++) + { + printf("%d ", pdeTestSaiPortMap.port_list[i].lane_list[j]); + } + printf("\n"); + + printf("Port Name: %s %d Total Lanes: %d Lanes: ", pdeTestPortConfigMap.port_list[i].name, + pdeTestPortConfigMap.port_list[i].speed, pdeTestPortConfigMap.port_list[i].total_lanes); + for (j = 0; j < pdeTestPortConfigMap.port_list[i].total_lanes; j++) + { + printf("%d ", pdeTestPortConfigMap.port_list[i].lane_list[j]); + } + printf("\n"); + +} +/* More detail on the SONiC code to parse the SAI port list can be found in portsorch.cpp in SONiC*/ +int saiUnitSonicTestPortConfigIniTest() +{ + int i, j, k; + int matching_entries = 0; + int failing_entries = 0; + int entry_found = 0; + + saiSonicPdeLoadPortConfig(); + saiSonicPdeLoadSaiPortMap(); + + CU_ASSERT(pdeTestPortConfigMap.total_ports == pdeTestSaiPortMap.total_ports); + if (pdeTestPortConfigMap.total_ports == pdeTestSaiPortMap.total_ports) + { + printf("PASS:"); + } + else + { + printf("FAIL:"); + } + printf("%d port entries found in port_config.ini, %d entries enumerated by SAI\n", pdeTestPortConfigMap.total_ports, pdeTestSaiPortMap.total_ports); + + for (i = 0; i < pdeTestPortConfigMap.total_ports; i++) + { + entry_found = 0; + for (j = 0; j < pdeTestSaiPortMap.total_ports && entry_found == 0; j++) + { + if ((pdeTestSaiPortMap.port_list[j].speed == pdeTestPortConfigMap.port_list[i].speed) && + (pdeTestSaiPortMap.port_list[j].total_lanes == pdeTestPortConfigMap.port_list[i].total_lanes)) + { + for (k = 0; k < pdeTestPortConfigMap.port_list[i].total_lanes; k++) + { + if (pdeTestPortConfigMap.port_list[i].lane_list[k] != pdeTestSaiPortMap.port_list[j].lane_list[k]) + { + break; + } + } + } + + if (k == pdeTestPortConfigMap.port_list[i].total_lanes) + { + entry_found = 1; + matching_entries++; + } + } + + if (entry_found == 1) + { + printf("PASS: %s entry matched with SAI Port ID: 0x%016lx\n", pdeTestPortConfigMap.port_list[i].name, pdeTestSaiPortMap.port_list[i].port_id); + } + else + { + printf("FAIL: %s entry not found in SAI port list!\n", pdeTestPortConfigMap.port_list[i].name); + failing_entries++; + } + } + + if (matching_entries == pdeTestPortConfigMap.total_ports) + { + printf("\nPASS: %d entries matched to SAI port list!", matching_entries); + } + else + { + printf("\nFAIL: %d entries not matched!", failing_entries); + CU_ASSERT(failing_entries == 0); + } + + printf("\n\n"); + printf("******************************************************\n"); + printf("SAI Port List Table - For Reference Only\n"); + printf("******************************************************\n"); + for (i = 0; i < pdeTestSaiPortMap.total_ports; i++) + { + printf("Port ID: 0x%016lx Speed: %d Total Lanes: %d Lanes: ", pdeTestSaiPortMap.port_list[i].port_id, + pdeTestSaiPortMap.port_list[i].speed, pdeTestSaiPortMap.port_list[i].total_lanes); + for (j = 0; j < pdeTestSaiPortMap.port_list[i].total_lanes; j++) + { + printf("%d ", pdeTestSaiPortMap.port_list[i].lane_list[j]); + } + printf("\n"); + } + printf("******************************************************\n"); + + printf("\n\n"); + printf("******************************************************\n"); + printf("port_config.ini Port List Table - For Reference Only\n"); + printf("******************************************************\n"); + for (i = 0; i < pdeTestPortConfigMap.total_ports; i++) + { + printf("Port Name: %s %d Total Lanes: %d Lanes: ", pdeTestPortConfigMap.port_list[i].name, + pdeTestPortConfigMap.port_list[i].speed, pdeTestPortConfigMap.port_list[i].total_lanes); + for (j = 0; j < pdeTestPortConfigMap.port_list[i].total_lanes; j++) + { + printf("%d ", pdeTestPortConfigMap.port_list[i].lane_list[j]); + } + printf("\n"); + } + printf("******************************************************\n"); + + return 0; + +} + +int saiUnitSonicPdeTrafficTest() +{ + sai_status_t rv = SAI_STATUS_SUCCESS; + int i, p, max_ports, queue_count; + sai_attribute_t switch_attr; + sai_attribute_t port_attr; + sai_object_id_t port_obj, port1_obj, port2_obj; + char cmd_str[256]; + int lport1, lport2; + int test_port1, test_port2; + char *p1; + char *p2; + + CU_ASSERT(SAI_STATUS_SUCCESS == saiUnitGetSwitchPortCount(&max_ports)); + switch_attr.id = SAI_SWITCH_ATTR_SRC_MAC_ADDRESS; + memset(switch_attr.value.mac, 0, sizeof(sai_mac_t)); + sai_mac_t smac = { 0x00, 0x44, 0x55, 0x55, 0x66, 0x66 }; + memcpy(switch_attr.value.mac, smac, sizeof(sai_mac_t)); + CU_ASSERT(SAI_STATUS_SUCCESS == saiUnitSetSwitchAttribute(&switch_attr)); + + /* Get Cpu queues */ + switch_attr.id = SAI_SWITCH_ATTR_CPU_PORT; + CU_ASSERT(SAI_STATUS_SUCCESS == saiUnitGetSwitchAttributes(1, &switch_attr)); + sai_object_id_t cpu_port = switch_attr.value.oid; + port_attr.id = SAI_PORT_ATTR_QOS_NUMBER_OF_QUEUES; + CU_ASSERT(SAI_STATUS_SUCCESS == saiUnitGetPortAttribute(cpu_port, &port_attr)); + queue_count = port_attr.value.u32; + port_attr.id = SAI_PORT_ATTR_QOS_QUEUE_LIST; + port_attr.value.objlist.count = queue_count; + port_attr.value.objlist.list = calloc(queue_count, sizeof(sai_object_id_t)); + CU_ASSERT(SAI_STATUS_SUCCESS == saiUnitGetPortAttribute(cpu_port, &port_attr)); + p = BRCM_SAI_GET_OBJ_VAL(sai_uint32_t, cpu_port); + for (i = 0; i < queue_count; i++) + { + qid[p][i] = port_attr.value.objlist.list[i]; + } + free(port_attr.value.objlist.list); + + saiSonicPdeLoadPortConfig(); + saiSonicPdeLoadSaiPortMap(); + + for (i = 0; i < num_ports_in_traffic_test; i += 2) + { + test_port1 = saiUnitTrafficGetPortFromConfig(i); + test_port2 = saiUnitTrafficGetPortFromConfig(i + 1); + + if (saiGetPortIdfromPortConfig(test_port1 - 1, &port1_obj) != 1) + { + printf("\nFAIL: Unable to retrieve SAI object for %s\n", pdeTestPortConfigMap.port_list[test_port1 - 1].name); + printf("Please verify your config.bcm and port_config.ini\n"); + + continue; + } + if (saiGetPortIdfromPortConfig(test_port2 - 1, &port2_obj) != 1) + { + printf("\nFAIL: Unable to retrieve SAI object for %s\n", pdeTestPortConfigMap.port_list[test_port2 - 1].name); + printf("Please verify your config.bcm and port_config.ini\n"); + + continue; + } + + printf("Test port: %d, SAI Port Object ID: 0x%016lx \n", test_port1, port1_obj); + printf("Test port: %d, SAI Port Object ID: 0x%016lx \n", test_port2, port2_obj); + + p1 = saiUnitGetBcmPortName(i); + p2 = saiUnitGetBcmPortName(i +1); + + lport1 = (port1_obj & 0xFF); + lport2 = (port2_obj & 0xFF); + + printf("\nTesting traffic between ports %d:%s:%s and %d:%s:%s\n", lport1, pdeTestPortConfigMap.port_list[test_port1 - 1].name, + p1, lport2, pdeTestPortConfigMap.port_list[test_port2 - 1].name, p2); + + saiUnitSetLogLevel(SAI_LOG_LEVEL_DEBUG); + + /* Enable ports in admin mode */ + port_obj = port1_obj; + port_attr.id = SAI_PORT_ATTR_ADMIN_STATE; + port_attr.value.booldata = TRUE; + CU_ASSERT(SAI_STATUS_SUCCESS == + saiUnitSetPortAttribute(port_obj, &port_attr)); + port_obj = port2_obj; + CU_ASSERT(SAI_STATUS_SUCCESS == + saiUnitSetPortAttribute(port_obj, &port_attr)); + + /* Wait some time for the ports to come up. */ + sleep(3); + + /* Prevent traffic from passing back to sender*/ + sprintf(cmd_str, "port %s stp=block\n", p2); + sai_driver_process_command(cmd_str); + + CU_ASSERT(SAI_STATUS_SUCCESS == saiUnitClearStats()); + CU_ASSERT(SAI_STATUS_SUCCESS == saiUnitSendFramesToHost(p1, TRAFFIC_FRAME_COUNT)); + rv = saiUnitValidateStatsRx(port2_obj, TRAFFIC_FRAME_COUNT); + + sprintf(cmd_str, "port %s stp=forward\n", p2); + sai_driver_process_command(cmd_str); + + if (rv == SAI_STATUS_SUCCESS) + { + printf("PASS: Successfully sent %d frames between %s and %s \n", TRAFFIC_FRAME_COUNT, + pdeTestPortConfigMap.port_list[test_port1 - 1].name, pdeTestPortConfigMap.port_list[test_port2 - 1].name); + } + else + { + printf("FAIL: Unable to send %d frames between %s and %s \n", TRAFFIC_FRAME_COUNT, + pdeTestPortConfigMap.port_list[test_port1 - 1].name, pdeTestPortConfigMap.port_list[test_port2 - 1].name); + + CU_ASSERT(SAI_STATUS_SUCCESS == rv); + } + + /* Disable ports in admin mode */ + port_obj = port1_obj; + port_attr.id = SAI_PORT_ATTR_ADMIN_STATE; + port_attr.value.booldata = FALSE; + CU_ASSERT(SAI_STATUS_SUCCESS == + saiUnitSetPortAttribute(port_obj, &port_attr)); + port_obj = port2_obj; + CU_ASSERT(SAI_STATUS_SUCCESS == + saiUnitSetPortAttribute(port_obj, &port_attr)); + + } + return 0; +} + +/* Smoke Suite */ +int saiSonicPdeAdd(void) +{ + pSonicPdeSuite = CU_add_suite("SONiC PDE tests", NULL, NULL); + if (NULL == pSonicPdeSuite) + { + printf("%s\n", CU_get_error_msg()); + return 1; + } + if (NULL == CU_ADD_TEST(pSonicPdeSuite, saiUnitSonicTestPortConfigIniTest)) + { + printf("%s\n", CU_get_error_msg()); + return 1; + } + + if (NULL == CU_ADD_TEST(pSonicPdeSuite, saiUnitSonicPdeTrafficTest)) + { + printf("%s\n", CU_get_error_msg()); + return 1; + } + + return 0; +} diff --git a/pde-test-host/pde-test-host/unittests/saiUnitCommon.c b/pde-test-host/pde-test-host/unittests/saiUnitCommon.c new file mode 100755 index 0000000..89d49e1 --- /dev/null +++ b/pde-test-host/pde-test-host/unittests/saiUnitCommon.c @@ -0,0 +1,258 @@ +/********************************************************************* + * + * Broadcom Proprietary and Confidential. (C) Copyright 2016-2018 Broadcom. + * All rights reserved. + * + ********************************************************************** + * + * @filename saiUnitCommon.c + * + * @purpose This file contains the common code for unit tests + * + * @component unit test + * + * @comments + * + * @create 20 Jan 2017 + * + * @end + * + **********************************************************************/ +#include "saiUnitUtil.h" + +#include + +extern int saiSonicPdeAdd(void); +extern CU_pSuite pSonicPdeSuite; + +extern CU_pSuite f_pRunningSuite; +extern CU_ErrorCode basic_initialize(void); +extern void console_registry_level_run(CU_pTestRegistry pRegistry); +static void logging_test_start_message_handler(const CU_pTest pTest, const CU_pSuite pSuite); +static void logging_test_complete_message_handler(const CU_pTest pTest, const CU_pSuite pSuite, const CU_pFailureRecord pFailureList); + +static void logging_all_tests_complete_message_handler(const CU_pFailureRecord pFailure); +typedef int (*saiUnitTestAddf)(void); + +struct +{ + saiTestId_t testId; + char *testName; + saiUnitTestAddf testFunc; +} saiUnitTestModules[] = +{ + { SAI_TEST_ID_ALL, "All", NULL }, + { SAI_TEST_ID_PDE, "Sonic PDE Tests", saiSonicPdeAdd }, +}; + +const char *saiUnitTestModuleNameGet(saiTestId_t testId) +{ + if ((testId < SAI_TEST_ID_ALL) || + (testId >= SAI_TEST_ID_MAX)) + { + return NULL; + } + return saiUnitTestModules[testId].testName; +} + +int saiUnitTestsRun(saiTestType_t testType, int testRunQA, saiTestId_t testId) +{ + int i; + + if (CUE_SUCCESS != CU_initialize_registry()) + { + return CU_get_error(); + } + + if (SAI_TEST_ID_ALL == testId) + { + for (i = SAI_TEST_ID_MIN; i < SAI_TEST_ID_MAX; i++) + { + if (0 != saiUnitTestModules[i].testFunc()) + { + printf("\r\nFailed to add %s Unit tests. Aborting.\r\n", saiUnitTestModules[i].testName); + return -1; + } + } + } + else if ((testId >= SAI_TEST_ID_MIN) && + (testId < SAI_TEST_ID_MAX)) + { + if (0 != saiUnitTestModules[testId].testFunc()) + { + printf("\r\nFailed to add %s Unit tests. Aborting.\r\n", saiUnitTestModules[testId].testName); + return -1; + } + } + else + { + printf("\r\nInvalid test id (%d) specified. Aborting.\r\n", testId); + } + + switch (testType) + { + case SAI_TEST_BASIC: + CU_basic_set_mode(CU_BRM_VERBOSE); + CU_set_suite_active(pSonicPdeSuite, CU_FALSE); + CU_basic_run_tests(); + CU_basic_show_failures(CU_get_failure_list()); + break; + + case SAI_TEST_AUTOMATED: + CU_set_output_filename("/tmp/CUnitAutomated"); + CU_set_suite_active(pSonicPdeSuite, CU_TRUE); + CU_automated_run_tests(); + CU_list_tests_to_file(); + break; + + case SAI_TEST_CONSOLE: + CU_console_run_tests(); + break; + /* To be used to save the test results in case of + crashes/switch disconects etc */ + case SAI_TEST_LOGGING: + CU_basic_set_mode(CU_BRM_VERBOSE); + basic_initialize(); + CU_set_test_start_handler(logging_test_start_message_handler); + /* Print to file the test assertions after each test run! */ + CU_set_test_complete_handler(logging_test_complete_message_handler); + /* Print test summary out as well at the end */ + CU_set_all_test_complete_handler(logging_all_tests_complete_message_handler); + console_registry_level_run(NULL); + break; + + default: + return -1; + } + + printf("\r\n"); + CU_cleanup_registry(); + return CU_get_error(); +} + +static char logFileName[256]; +static char* saiFileBase = "/tmp/SAIlogs/SAI_"; +static FILE* fp = NULL; + +void set_logging_file_name(char* testName) +{ + memset(logFileName, '\0', sizeof(logFileName)); + strcpy(logFileName, saiFileBase); + strncat(logFileName, testName, 128); +} + +/*------------------------------------------------------------------------*/ +/** Handler function called at start of each test. + * @param pTest The test being run. + * @param pSuite The suite containing the test. + */ +void logging_test_start_message_handler(const CU_pTest pTest, const CU_pSuite pSuite) +{ + assert(NULL != pSuite); + assert(NULL != pTest); + + assert(NULL != pTest->pName); + if ((NULL == f_pRunningSuite) || (f_pRunningSuite != pSuite)) { + assert(NULL != pSuite->pName); + fprintf(stdout, "\n%s: %s", "Suite", pSuite->pName); + fprintf(stdout, "\n %s: ...Test", pTest->pName); + f_pRunningSuite = pSuite; + } + else { + fprintf(stdout, "\n %s: ...Test", pTest->pName); + } + +} + + +static void logging_all_tests_complete_message_handler(const CU_pFailureRecord pFailure) +{ + time_t t = time(NULL); + struct tm tm = *localtime(&t); + char timestr[128]; + sprintf(timestr, "now: %d-%d-%d %d:%d:%d\n", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); + + CU_UNREFERENCED_PARAMETER(pFailure); /* not used in basic interface */ + printf("\n\n"); + CU_print_run_results(stdout); + /* Also print to file */ + fp = NULL; + system("mkdir -p /tmp/SAIlogs"); + fp = fopen("/tmp/SAIlogs/AllResultsSummary", "a"); + if (fp == NULL) + { + fprintf(stdout,"Error getting log file %s\n", logFileName); + } + else + { + fprintf(fp,"\n====================================\n"); + fprintf(fp, "\n\nTest results at %s\n\n", timestr); + fprintf(fp,"\n====================================\n"); + CU_print_run_results(fp); + } + printf("\n"); + if (fp != NULL) + { + fclose(fp); + } +} + +/*------------------------------------------------------------------------*/ +/** Handler function called at completion of each test. + * @param pTest The test being run. + * @param pSuite The suite containing the test. + * @param pFailure Pointer to the 1st failure record for this test. + */ + void logging_test_complete_message_handler(const CU_pTest pTest, + const CU_pSuite pSuite, + const CU_pFailureRecord pFailureList) +{ + CU_pFailureRecord pFailure = pFailureList; + int i; + time_t t = time(NULL); + struct tm tm = *localtime(&t); + char timestr[128]; + sprintf(timestr, "now: %d-%d-%d %d:%d:%d\n", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); + + assert(NULL != pSuite); + assert(NULL != pTest); + fp = NULL; + + if (NULL == pFailure) { + fprintf(stdout, "\t...passed"); + } + else { + /* Only write test files if they fail */ + set_logging_file_name(pTest->pName); + system("mkdir -p /tmp/SAIlogs"); + fp = fopen(logFileName, "w"); + if (fp == NULL) + { + fprintf(stdout,"Error getting log file %s\n", logFileName); + } + fprintf(stdout, "FAILED"); + fprintf(stdout, "\nSuite %s, Test %s had failures:", pSuite->pName, pTest->pName); + if (fp != NULL) + { + fprintf(fp,"FAILED"); + fprintf(fp, "\nTime %s Suite %s, Test %s had failures:", + timestr, + pSuite->pName, pTest->pName); + } + } + if (fp != NULL) { + for (i = 1 ; (NULL != pFailure) ; pFailure = pFailure->pNext, i++) { + fprintf(fp, "\n %d. %s:%u - %s", i, + (NULL != pFailure->strFileName) ? pFailure->strFileName : "", + pFailure->uiLineNumber, + (NULL != pFailure->strCondition) ? pFailure->strCondition : ""); + + } + } + if (fp!=NULL) + { + fclose(fp); + } +} diff --git a/pde-test-host/pde-test-host/unittests/saiUnitTest.h b/pde-test-host/pde-test-host/unittests/saiUnitTest.h new file mode 100755 index 0000000..ee846ef --- /dev/null +++ b/pde-test-host/pde-test-host/unittests/saiUnitTest.h @@ -0,0 +1,47 @@ +/********************************************************************* + * + * Broadcom Proprietary and Confidential. (C) Copyright 2016-2018 Broadcom. + * All rights reserved. + * + ********************************************************************** + * + * @filename saiUnitTest.h + * + * @purpose This file contains the definitions for invoking the unit tests + * + * @component unit test + * + * @comments + * + * @create 20 Jan 2017 + * + * @author gmirek + * + * @end + * + **********************************************************************/ +#ifndef INCLUDE_SAI_UT_H +#define INCLUDE_SAI_UT_H + +typedef enum +{ + SAI_TEST_BASIC, + SAI_TEST_AUTOMATED, + SAI_TEST_CONSOLE, + SAI_TEST_LOGGING, + SAI_TEST_CURSES, /* This option is not supported. */ + SAI_TEST_MAX +} saiTestType_t; + +typedef enum +{ + SAI_TEST_ID_ALL = 0, + SAI_TEST_ID_MIN = 1, + SAI_TEST_ID_PDE = SAI_TEST_ID_MIN, + SAI_TEST_ID_MAX +} saiTestId_t; + +extern const char *saiUnitTestModuleNameGet(saiTestId_t testId); +extern int saiUnitTestsRun(saiTestType_t testType, int testRunQA, saiTestId_t testId); + +#endif /* INCLUDE_SAI_UT_H */ diff --git a/pde-test-host/pde-test-host/unittests/saiUnitUtil.c b/pde-test-host/pde-test-host/unittests/saiUnitUtil.c new file mode 100755 index 0000000..4b2341e --- /dev/null +++ b/pde-test-host/pde-test-host/unittests/saiUnitUtil.c @@ -0,0 +1,570 @@ +/********************************************************************* + * + * Broadcom Proprietary and Confidential. (C) Copyright 2016-2018 Broadcom. + * All rights reserved. + * + ********************************************************************** + * + * @filename saiUnitUtil.c + * + * @purpose This file contains utility functions for unit tests + * + * @component unit test + * + * @comments + * + * @create 20 Jan 2013 + * + * @end + * + **********************************************************************/ +#include "saiUnitUtil.h" + +static sai_object_id_t ports[_BRCM_SAI_MAX_PORTS]; +static sai_object_list_t port_list = { _BRCM_SAI_MAX_PORTS, ports }; +/* Bridge Ports */ +static sai_object_id_t b_ports[_BRCM_SAI_MAX_PORTS]; +static sai_object_list_t b_port_list = { _BRCM_SAI_MAX_PORTS, b_ports }; +bool switch_mac_init = FALSE; +int stdoutBackupFd; +FILE *nullOut = NULL; + +void saiHideConsoleOutput(void) +{ + /* Open re-directed stdout */ + stdoutBackupFd = dup(fileno(stdout)); + fflush(stdout); + nullOut = fopen("/dev/null", "w"); + dup2(fileno(nullOut), fileno(stdout)); +} + +void saiShowConsoleOutput(void) +{ + /* Close re-directed stdout */ + fflush(stdout); + fclose(nullOut); + + /* Restore stdout */ + dup2(stdoutBackupFd, fileno(stdout)); + close(stdoutBackupFd); +} + +int +saiUnitGetSwitchAttributes(uint32_t attr_count, sai_attribute_t *switch_attr) +{ + sai_status_t rv = SAI_STATUS_SUCCESS; + + rv = sai_switch_apis->get_switch_attribute(0, attr_count, switch_attr); + if (SAI_STATUS_SUCCESS != rv) + { + return SAI_STATUS_FAILURE; + } + + return rv; +} + +int +saiUnitSetSwitchAttribute(sai_attribute_t *switch_attr) +{ + sai_status_t rv = SAI_STATUS_SUCCESS; + sai_mac_t null_mac = { 0 }; + sai_mac_t default_switch_mac = { 0x00, 0x05, 0x06, 0x08, 0x05, 0x00 }; + + if (SAI_SWITCH_ATTR_SRC_MAC_ADDRESS == switch_attr->id) + { + if (TRUE == switch_mac_init) + { + return rv; + } + if (0 == strncmp((const char *) switch_attr->value.mac, + (const char *) null_mac, + sizeof(switch_attr->value.mac))) + { + memcpy(switch_attr->value.mac, default_switch_mac, + sizeof(switch_attr->value.mac)); + } + rv = sai_switch_apis->set_switch_attribute(0, switch_attr); + if (rv == SAI_STATUS_SUCCESS || rv == SAI_STATUS_NOT_SUPPORTED) + { + return SAI_STATUS_SUCCESS;//As we might have already set during CUnit _setup_config + } + else{ + return rv; + } + } + + rv = sai_switch_apis->set_switch_attribute(0, switch_attr); + if (SAI_STATUS_SUCCESS != rv) + { + return SAI_STATUS_FAILURE; + } + + if (SAI_SWITCH_ATTR_SRC_MAC_ADDRESS == switch_attr->id) + { + switch_mac_init = TRUE; + } + + return rv; +} + +int +saiUnitSetPortAttribute(sai_object_id_t port_id, sai_attribute_t *port_attr) +{ + sai_status_t rv = SAI_STATUS_SUCCESS; + + rv = sai_port_apis->set_port_attribute(port_id, port_attr); + if (SAI_STATUS_SUCCESS != rv) + { + return SAI_STATUS_FAILURE; + } + + return rv; +} + +int +saiUnitGetPortAttribute(sai_object_id_t port_id, sai_attribute_t *port_attr) +{ + sai_status_t rv = SAI_STATUS_SUCCESS; + + rv = sai_port_apis->get_port_attribute(port_id, 1, port_attr); + if (SAI_STATUS_SUCCESS != rv) + { + return SAI_STATUS_FAILURE; + } + + return rv; +} + + +int saiUnitSaiIndexGet(int bcmport) +{ + int i, port_count; + saiUnitGetSwitchPortCount(&port_count); + for (i=0;iget_switch_attribute(0, 1, &switch_attr); + if (SAI_STATUS_SUCCESS != rv) + { + return SAI_STATUS_FAILURE; + } + switch_attr.id = SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID; + rv = sai_switch_apis->get_switch_attribute(0, 1, &switch_attr); + if (SAI_STATUS_SUCCESS != rv) + { + return SAI_STATUS_FAILURE; + } + rv = sai_bridge_apis->get_bridge_attribute(switch_attr.value.oid, 1, &b_attr); + if (SAI_STATUS_SUCCESS != rv) + { + return SAI_STATUS_FAILURE; + } + else + { + port_list.count = b_port_list.count = b_attr.value.objlist.count; + for (p=0; pget_bridge_port_attribute(bp_attr.value.oid, 1, &bp_attr); + if (SAI_STATUS_SUCCESS != rv) + { + return SAI_STATUS_FAILURE; + } + else + { + port_list.list[p] = bp_attr.value.oid; + } + } + } + ports_inited = TRUE; + } + *port_count = port_list.count; + + return rv; +} + +sai_object_id_t +saiUnitGetPortObject(int index) +{ + if (index > port_list.count) + { + return (sai_object_id_t) NULL; + } + else + { + return port_list.list[index]; + } +} + +int +saiUnitGetLogicalPort(int index) +{ + if (index > port_list.count) + { + return (sai_object_id_t) NULL; + } + else + { + return index + 1; + } +} + +sai_object_id_t +saiUnitGetBridgePortObject(int index) +{ + if (index > b_port_list.count) + { + return (sai_object_id_t) NULL; + } + else + { + return b_port_list.list[index]; + } +} + +int saiUnitValidateStatsRx(sai_object_id_t port_obj, int expected) +{ + int rv = SAI_STATUS_SUCCESS; + uint64_t counters[1] = { 0 }; + sai_port_stat_t cids[1] = + { + SAI_PORT_STAT_IF_IN_UCAST_PKTS + }; + + rv = sai_port_apis->get_port_stats(port_obj, 1, cids, &counters[0]); + if (SAI_STATUS_SUCCESS != rv) + { + return rv; + } + + if (expected != counters[0]) + { + return SAI_STATUS_FAILURE; + } + return rv; +} + +int saiUnitValidateStats(int port, int expected) +{ + int rv = SAI_STATUS_SUCCESS; + uint64_t counters[1] = { 0 }; + sai_object_id_t port_obj; + sai_port_stat_t cids[1] = + { + SAI_PORT_STAT_IF_OUT_UCAST_PKTS + }; + + port_obj = saiUnitGetPortObject(port); + rv = sai_port_apis->get_port_stats(port_obj, 1, cids, &counters[0]); + if (SAI_STATUS_SUCCESS != rv) + { + return rv; + } + + if (expected != counters[0]) + { + return SAI_STATUS_FAILURE; + } + return rv; +} + +/* Retreive port stats */ +uint64_t saiUnitGetPortStats(int port) +{ + int rv = SAI_STATUS_SUCCESS; + uint64_t counters[1] = { 0 }; + sai_object_id_t port_obj; + sai_port_stat_t cids[1] = + { + SAI_PORT_STAT_IF_OUT_UCAST_PKTS + }; + + port_obj = saiUnitGetPortObject(port); + rv = sai_port_apis->get_port_stats(port_obj, 1, cids, &counters[0]); + if (rv != SAI_STATUS_SUCCESS){ + printf("Failed to get port stats.Error is %d\n", rv); + return -1; + } + return counters[0]; +} + +/*Genric function to send the Frames usning driver_process_command*/ +sai_status_t saiUnitSendFramesGeneric(char *commandBuf, char *port){ + /* Hide console output */ + saiHideConsoleOutput(); + sai_driver_process_command(commandBuf); + memset(commandBuf,'\0',MAX_FRAME_SIZE); + sprintf(commandBuf,"tx 1 pbm=%s data=\'\'",port); + sai_driver_process_command(commandBuf); + /* Show console output */ + saiShowConsoleOutput(); + return SAI_STATUS_SUCCESS; +} + +int saiUnitFormDHCPv6Packet(char *port,char *commandBuf){ + /* To From DHCPV6 generic packet */ + sprintf(commandBuf,"tx 1 pbm=%s data=\'000000000004000AF7819F9786dd6000000000361140" + "1111111111111111111111111111111133333333333333333333333333333333" + "022302220036423511121314151617181920\'",port); + return SAI_STATUS_SUCCESS; + +} + + +/* This is a specific routine to check queue stats for Service pool-0 destined traffic + * Service pool 1 destined traffic has internal priority set to 7 + * */ +int saiUnitValidateQueueStatsCount(int port, sai_object_id_t queue, int expected) +{ + int rv = SAI_STATUS_SUCCESS; + uint64_t counters[1] = { 0 }; + sai_queue_stat_t cids[1] = + { + SAI_QUEUE_STAT_PACKETS + }; + rv = sai_qos_queue_apis->get_queue_stats(qid[port][queue], 1, cids, &counters[0]); + if (SAI_STATUS_SUCCESS != rv) + { + return rv; + } + + if (expected != counters[0]) + { + return SAI_STATUS_FAILURE; + } + return rv; +} +/*Do clear stats*/ +sai_status_t saiUnitClearStats(){ + int rv=SAI_STATUS_FAILURE; + rv = sai_driver_process_command("clear c"); + return rv; +} + +sai_status_t saiUnitSetLogLevel(sai_log_level_t level) +{ + sai_status_t rv; + sai_api_t api; + + for (api = SAI_API_UNSPECIFIED+1; api <= _SAI_API_ID_MAX; api++) + { + rv = sai_log_set(api, level); + if (rv != SAI_STATUS_SUCCESS) + { + return rv; + } + } + return SAI_STATUS_SUCCESS; +} + +int saiUnitTrafficGetPortFromConfig(int index){ + if(index > num_ports_in_test) + return -1; + else + return pde_traffic_test_port_list[index]; +} + +int saiUnitGetPortFromConfig(int index){ + if(index > num_ports_in_test) + return -1; + else + return sai_port_index_list[index]; +} + + +int saiUnitGetLogicalPortFromConfig(int index){ + if(index > num_ports_in_test) + return -1; + else + return bcm_port_list[index]; +} + +char* saiUnitGetBcmPortName(int index){ + if(index > num_ports_in_test) + return NULL; + else + return bcm_port_list_names[index]; +} + +sai_status_t saiUnitSetQueueAttribute(int port, int queue, sai_attribute_t *qattr){ + sai_status_t rv = SAI_STATUS_SUCCESS; + rv = sai_qos_queue_apis->set_queue_attribute(qid[port][queue], qattr); + return rv; +} + +sai_status_t saiUnitSetRIFAttribute(sai_object_id_t rif_obj, sai_attribute_t *rattr){ + sai_status_t rv = SAI_STATUS_SUCCESS; + rv = sai_router_intf_apis->set_router_interface_attribute(rif_obj, rattr); + return rv; +} + +int saiUnitCheckObjInList(sai_object_id_t obj, sai_object_list_t objlist){ + int i = 0; + for(i = 0;i < objlist.count; i++){ + if(obj == objlist.list[i]) + return SAI_STATUS_SUCCESS; + } + return SAI_STATUS_FAILURE; +} + +/* Get the port list and bridge port list after warmboot */ +sai_status_t saiUnitGetSwitchPortCountAfterWB(){ + sai_status_t rv = SAI_STATUS_SUCCESS; + + port_list.count = _BRCM_SAI_MAX_PORTS;//Reset them to max + port_list.list = ports; + b_port_list.count = _BRCM_SAI_MAX_PORTS; + b_port_list.list = b_ports; + + sai_attribute_t switch_attr = { SAI_SWITCH_ATTR_PORT_LIST, .value.objlist = b_port_list }; + sai_attribute_t b_attr = { SAI_BRIDGE_ATTR_PORT_LIST, .value.objlist = b_port_list }; + sai_attribute_t bp_attr = { SAI_BRIDGE_PORT_ATTR_PORT_ID }; + int p; + rv = sai_switch_apis->get_switch_attribute(0, 1, &switch_attr); + if (SAI_STATUS_SUCCESS != rv) + { + return SAI_STATUS_FAILURE; + } + switch_attr.id = SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID; + rv = sai_switch_apis->get_switch_attribute(0, 1, &switch_attr); + if (SAI_STATUS_SUCCESS != rv) + { + return SAI_STATUS_FAILURE; + } + rv = sai_bridge_apis->get_bridge_attribute(switch_attr.value.oid, 1, &b_attr); + if (SAI_STATUS_SUCCESS != rv) + { + return SAI_STATUS_FAILURE; + } + else + { + port_list.count = b_port_list.count = b_attr.value.objlist.count; + for (p=0; pget_bridge_port_attribute(bp_attr.value.oid, 1, &bp_attr); + if (SAI_STATUS_SUCCESS != rv) + { + return SAI_STATUS_FAILURE; + } + else + { + port_list.list[p] = bp_attr.value.oid; + } + } + } + //*port_count = port_list.count; + return rv; +} + +sai_status_t saiUnitRemovePortsFromDefaultVLAN(int max_ports) +{ + sai_status_t rv = SAI_STATUS_SUCCESS; + int i; + sai_object_id_t *vlan_port_objs; + sai_attribute_t switch_attr, vattr; + sai_attribute_t port_list_vlan[] = + { + { SAI_VLAN_MEMBER_ATTR_VLAN_ID }, + { SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID }, + { SAI_VLAN_MEMBER_ATTR_VLAN_TAGGING_MODE } + }; + + switch_attr.id = SAI_SWITCH_ATTR_DEFAULT_VLAN_ID; + rv = saiUnitGetSwitchAttributes(1, &switch_attr); + if (SAI_STATUS_SUCCESS != rv) + { + return rv; + } + + vlan_port_objs = (sai_object_id_t *) calloc(max_ports, sizeof(sai_object_id_t)); + vattr.id = SAI_VLAN_ATTR_MEMBER_LIST; + vattr.value.objlist.count = max_ports; + vattr.value.objlist.list = vlan_port_objs; + rv = sai_vlan_apis->get_vlan_attribute(switch_attr.value.oid, 1, &vattr); + if (SAI_STATUS_SUCCESS != rv) + { + free(vlan_port_objs); + return rv; + } + port_list_vlan[0].value.oid = switch_attr.value.oid; + for (i = 0; i < max_ports; i++) + { + /* Remove port from default vlan */ + rv = sai_vlan_apis->remove_vlan_member(vlan_port_objs[i]); + if (SAI_STATUS_SUCCESS != rv) + { + free(vlan_port_objs); + return rv; + } + } + free(vlan_port_objs); + return rv; +} + +sai_status_t saiUnitRestorePortsToDefaultVLAN(int max_ports) +{ + sai_status_t rv = SAI_STATUS_SUCCESS; + int i; + sai_object_id_t vlan_port_obj; + sai_attribute_t switch_attr; + sai_attribute_t port_list_vlan[] = + { + { SAI_VLAN_MEMBER_ATTR_VLAN_ID }, + { SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID }, + { SAI_VLAN_MEMBER_ATTR_VLAN_TAGGING_MODE } + }; + + switch_attr.id = SAI_SWITCH_ATTR_DEFAULT_VLAN_ID; + rv = saiUnitGetSwitchAttributes(1, &switch_attr); + if (SAI_STATUS_SUCCESS != rv) + { + return rv; + } + + port_list_vlan[0].value.oid = switch_attr.value.oid; + for (i = 0; i < max_ports; i++) + { + port_list_vlan[1].value.oid = saiUnitGetBridgePortObject(i); + port_list_vlan[2].value.s32 = SAI_VLAN_TAGGING_MODE_UNTAGGED; + rv = sai_vlan_apis->create_vlan_member(&vlan_port_obj, + 0, + COUNTOF(port_list_vlan), + port_list_vlan); + } + return rv; +} + +sai_status_t saiUnitGetLagMemberObject(sai_object_id_t *lag_mbr_obj, + sai_object_id_t lag_obj, + sai_object_id_t port_obj){ + lag_member_port_info *node = root_node; + //traverse tlll we find the lag member object for the lag_obj and port_obj combination + while (node){ + if((node->lag_obj == lag_obj) && (node->port_obj == port_obj)){ + *lag_mbr_obj = node->lag_mbr_obj; + return SAI_STATUS_SUCCESS; + } + else{ + node = node->next; + } + } + return SAI_STATUS_FAILURE; +} diff --git a/pde-test-host/pde-test-host/unittests/saiUnitUtil.h b/pde-test-host/pde-test-host/unittests/saiUnitUtil.h new file mode 100755 index 0000000..8552bff --- /dev/null +++ b/pde-test-host/pde-test-host/unittests/saiUnitUtil.h @@ -0,0 +1,185 @@ +/********************************************************************* + * + * Broadcom Proprietary and Confidential. (C) Copyright 2016-2018 Broadcom. + * All rights reserved. + * + ********************************************************************** + * + * @filename saiUnitUtil.h + * + * @purpose This file contains the definitions for utility functions + * used within the unit tests + * + * @component unit test + * + * @comments + * + * @create 20 Jan 2017 + * + * @end + * + **********************************************************************/ +#ifndef INCLUDE_SAI_UT_UTIL_H +#define INCLUDE_SAI_UT_UTIL_H + +#include +#include +#include +#include +#include "sai.h" +#include "saiswitch.h" +#include "brcm_sai_common.h" +#include "saiUnitTest.h" +#include "CUnit.h" +#include "Basic.h" +#include "Console.h" +#include "Automated.h" +extern sai_switch_api_t *sai_switch_apis; +extern sai_port_api_t *sai_port_apis; +extern sai_queue_api_t *sai_qos_queue_apis; +extern sai_vlan_api_t *sai_vlan_apis; +extern sai_fdb_api_t *sai_fdb_apis; +extern sai_virtual_router_api_t *sai_router_apis; +extern sai_router_interface_api_t *sai_router_intf_apis; +extern sai_neighbor_api_t *sai_neighbor_apis; +extern sai_next_hop_api_t *sai_next_hop_apis; +extern sai_next_hop_group_api_t *sai_next_hop_grp_apis; +extern sai_route_api_t *sai_route_apis; +extern sai_hostif_api_t *sai_hostif_apis; +extern sai_lag_api_t *sai_lag_apis; +extern sai_tunnel_api_t *sai_tunnel_apis; +extern sai_bridge_api_t *sai_bridge_apis; +extern sai_policer_api_t *sai_policer_apis; +extern sai_acl_api_t *sai_acl_apis; +extern sai_mirror_api_t *sai_mirror_apis; +extern sai_qos_map_api_t *sai_qos_map_apis; +extern sai_udf_api_t *sai_udf_apis; +extern sai_hash_api_t *sai_hash_apis; +extern sai_wred_api_t *sai_wred_apis; +extern sai_scheduler_api_t *sai_qos_scheduler_apis; +extern sai_scheduler_group_api_t *sai_qos_sched_group_apis; +extern sai_buffer_api_t *sai_buffer_apis; +extern int sai_driver_shell(); +extern int sai_driver_process_command(char *commandBuf); +int saiUnitGetSwitchPortCount(int *port_count); +sai_object_id_t saiUnitGetPortObject(int index); +int saiUnitGetLogicalPort(int index); +sai_object_id_t saiUnitGetBridgePortObject(int index); +int saiUnitGetSwitchAttributes(uint32_t attr_count, + sai_attribute_t *switch_attr); +int saiUnitSetSwitchAttribute(sai_attribute_t *switch_attr); +int saiUnitSetPortAttribute(sai_object_id_t port_id, + sai_attribute_t *port_attr); +int saiUnitGetPortAttribute(sai_object_id_t port_id, + sai_attribute_t *port_attr); +void saiHideConsoleOutput(void); +void saiShowConsoleOutput(void); +int saiUnitValidateStats(int port, int expected); +int saiUnitValidateStatsRx(sai_object_id_t port_obj, int expected); +sai_status_t saiUnitSendFramesGeneric(char *commandbuf, char *port);/* Generic routine to send frames */ +sai_status_t saiUnitValidateQueueStats(int port, sai_object_id_t queue_id, int expected); +sai_status_t saiUnitValidateQueueStatsCount(int port, sai_object_id_t queue_id, int expected); +int saiUnitFormDHCPv6Packet(char *port,char *commandBuf); +sai_status_t saiUnitClearStats(); +sai_status_t saiUnitSetLogLevel(sai_log_level_t level); +int saiUnitGetPortFromConfig(int index); +int saiUnitGetLogicalPortFromConfig(int index); +char* saiUnitGetBcmPortName(int index); +sai_status_t saiUnitSetQueueAttribute(int port, int queue, sai_attribute_t *queue_attr); +sai_status_t saiUnitSetRIFAttribute(sai_object_id_t rif_obj, sai_attribute_t *rattr); +uint64_t saiUnitGetPortStats(int port); +int saiUnitCheckObjInList(sai_object_id_t obj, sai_object_list_t objlist); +sai_status_t saiUnitRemovePortsFromDefaultVLAN(int max_ports); +sai_status_t saiUnitRestorePortsToDefaultVLAN(int max_ports); +sai_status_t saiUnitGetLagMemberObject(sai_object_id_t *lag_mbr_obj, + sai_object_id_t lag_obj, + sai_object_id_t port_obj); +extern int saiUnitAddMemberToLagList(sai_object_id_t lag_obj, sai_object_id_t port_obj); +extern int saiUnitRemoveMemberFromLagList(sai_object_id_t lag_obj, sai_object_id_t port_obj); +extern int saiUnitSaiIndexGet(int bcmport); +#define _SAI_MAX_PORTS _BRCM_SAI_MAX_PORTS +#define MAX_FRAME_SIZE 255 +#define _SAI_MAX_QUEUES 64 + +typedef struct _lag_member_port_info{ + sai_object_id_t lag_obj; + sai_object_id_t lag_mbr_obj; + sai_object_id_t port_obj; + struct _lag_member_port_info *next; +}lag_member_port_info; + +/* To fetch test config data */ +extern int num_ports_in_test; +extern int num_ports_in_traffic_test; +extern int bcm_port_list[_SAI_MAX_PORTS]; +extern int sai_port_index_list[_SAI_MAX_PORTS]; +extern char* bcm_port_list_names[_SAI_MAX_PORTS]; +extern int bcm_loopback_port_list[_SAI_MAX_PORTS]; +extern int pde_traffic_test_port_list[_SAI_MAX_PORTS]; +extern char *mmu_init_config; +extern int capture_enable; +extern int warmboot_enable; +extern sai_object_id_t qid[_SAI_MAX_PORTS][_SAI_MAX_QUEUES]; +extern sai_uint32_t port_loopback_mode; +extern uint32_t sdk_shut_time; +#ifndef _SAI_API_ID_MIN +#define _SAI_API_ID_MIN SAI_API_UNSPECIFIED+1 +#endif +#ifndef _SAI_API_ID_MAX +#define _SAI_API_ID_MAX SAI_API_BRIDGE +#endif +extern char* chipid; +extern lag_member_port_info *root_node; + +#define CPU_PG 7 +/** Intrinsic buffer descriptor. + * + * NOTE: This is intended to be used as a basic data type that can be + * passed directly between functions -- keep it small and simple. + * To use this as an IN/OUT or OUT value, pass a pointer to the + * element so that the called routine can update the 'size' field + * with the actual content length being output. + * + * NOTE: When setting the 'size' field to indicate the amount of data + * contained in the buffer, the conventional usage is to account + * for all bytes including any string termination characters + * (e.g. strlen()+1). + */ + +typedef struct +{ + /** total buffer size (IN) / content length (OUT) */ + uint32_t size; + /** ptr to buffer starting location */ + char *pstart; +} saiBuffDesc; + + +#if 0 //Enable this for TH3 testing +#define SAI_PORT_INTERNAL_LOOPBACK_MODE_PHY SAI_PORT_INTERNAL_LOOPBACK_MODE_MAC +#endif + +#define SAI_CUNIT_PRINTF(__verbosity, __format, ...) \ + do \ + { \ + char buf[200]; \ + saiBuffDesc message; \ + int len; \ + \ + if (saiDebugLvlGet() >= __verbosity) \ + { \ + len = snprintf(buf, sizeof(buf), __format, __VA_ARGS__); \ + if (sizeof(buf) <= len) \ + { \ + buf[sizeof(buf) - 1] = 0; \ + len = sizeof(buf) - 1; \ + } \ + \ + message.pstart = buf; \ + message.size = len + 1; \ + saiCltLogBuf(0, message); \ + } \ + } while (0) + +#endif /* INCLUDE_SAI_UT_UTIL_H */ + diff --git a/sonic-pde-tests/MANIFEST.in b/sonic-pde-tests/MANIFEST.in new file mode 100644 index 0000000..e69de29 diff --git a/sonic-pde-tests/docs/Makefile b/sonic-pde-tests/docs/Makefile new file mode 100644 index 0000000..bb72cd8 --- /dev/null +++ b/sonic-pde-tests/docs/Makefile @@ -0,0 +1,216 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +.PHONY: clean +clean: + rm -rf $(BUILDDIR)/* + +.PHONY: html +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +.PHONY: dirhtml +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +.PHONY: singlehtml +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +.PHONY: pickle +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +.PHONY: json +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +.PHONY: htmlhelp +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +.PHONY: qthelp +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/sonic_pde_tests.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/sonic_pde_tests.qhc" + +.PHONY: applehelp +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +.PHONY: devhelp +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/sonic_pde_tests" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/sonic_pde_tests" + @echo "# devhelp" + +.PHONY: epub +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +.PHONY: latex +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +.PHONY: latexpdf +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: latexpdfja +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: text +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +.PHONY: man +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +.PHONY: texinfo +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +.PHONY: info +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +.PHONY: gettext +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +.PHONY: changes +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +.PHONY: linkcheck +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +.PHONY: doctest +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +.PHONY: coverage +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +.PHONY: xml +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +.PHONY: pseudoxml +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/sonic-pde-tests/docs/README.rst b/sonic-pde-tests/docs/README.rst new file mode 100644 index 0000000..b6c92ac --- /dev/null +++ b/sonic-pde-tests/docs/README.rst @@ -0,0 +1,26 @@ +sonic_pde_tests +================ + +This package is a part of the SONiC Platform Development Kit (PDK) and packaged +under the SONiC Platform Development Environment (PDE). + +build +===== +- get source + +- cd && ./build.sh + + (generates sonic_pde_tests-.deb) + +install +======= + +- remove existing ifupdown package + dpkg -r sonic_pde_tests + +- install sonic_pde_tests using `dpkg -i` + +- or install from deb + dpkg -i sonic_pde_tests-.deb + + diff --git a/sonic-pde-tests/docs/source/conf.py b/sonic-pde-tests/docs/source/conf.py new file mode 100644 index 0000000..0d01213 --- /dev/null +++ b/sonic-pde-tests/docs/source/conf.py @@ -0,0 +1,300 @@ +# -*- coding: utf-8 -*- +# +# sonic_pde_tests documentation build configuration file, created by +# sphinx-quickstart on Wed Jul 31 12:33:51 2019. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath('../../')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.napoleon', + 'sphinx.ext.doctest', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'sonic_pde_tests' +copyright = u'2019, Broadcom' +author = u'Broadcom' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = u'0.0.1' +# The full version, including alpha/beta/rc tags. +release = u'0.0.1' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'sonic_pde_testsdoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'sonic_pde_tests.tex', u'sonic\\_pde\\_tests Documentation', + u'Broadcom', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'sonic_pde_tests', u'sonic_pde_tests Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'sonic_pde_tests', u'sonic_pde_tests Documentation', + author, 'sonic_pde_tests', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + +# Napoleon settings +napoleon_google_docstring = True +napoleon_numpy_docstring = False +napoleon_include_init_with_doc = False +napoleon_include_private_with_doc = False +napoleon_include_special_with_doc = True +napoleon_use_admonition_for_examples = False +napoleon_use_admonition_for_notes = False +napoleon_use_admonition_for_references = False +napoleon_use_ivar = False +napoleon_use_param = True +napoleon_use_rtype = True diff --git a/sonic-pde-tests/docs/source/index.rst b/sonic-pde-tests/docs/source/index.rst new file mode 100644 index 0000000..9c2a79d --- /dev/null +++ b/sonic-pde-tests/docs/source/index.rst @@ -0,0 +1,22 @@ +.. sonic_pde_tests documentation master file, created by + sphinx-quickstart on Wed Jul 31 12:33:51 2019. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to sonic_pde_tests's documentation! +=========================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + +.. include:: ../README.rst + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/sonic-pde-tests/docs/source/modules.rst b/sonic-pde-tests/docs/source/modules.rst new file mode 100644 index 0000000..9fa8dc9 --- /dev/null +++ b/sonic-pde-tests/docs/source/modules.rst @@ -0,0 +1,7 @@ +sonic_pde_tests +=============== + +.. toctree:: + :maxdepth: 4 + + sonic_pde_tests diff --git a/sonic-pde-tests/docs/source/sonic_pde_tests.rst b/sonic-pde-tests/docs/source/sonic_pde_tests.rst new file mode 100644 index 0000000..0baac08 --- /dev/null +++ b/sonic-pde-tests/docs/source/sonic_pde_tests.rst @@ -0,0 +1,134 @@ +sonic_pde_tests package +======================= + +Submodules +---------- + +sonic_pde_tests.conftest module +------------------------------- + +.. automodule:: sonic_pde_tests.conftest + :members: + :undoc-members: + :show-inheritance: + +sonic_pde_tests.test_bmc module +------------------------------- + +.. automodule:: sonic_pde_tests.test_bmc + :members: + :undoc-members: + :show-inheritance: + +sonic_pde_tests.test_config module +---------------------------------- + +.. automodule:: sonic_pde_tests.test_config + :members: + :undoc-members: + :show-inheritance: + +sonic_pde_tests.test_cpld module +-------------------------------- + +.. automodule:: sonic_pde_tests.test_cpld + :members: + :undoc-members: + :show-inheritance: + +sonic_pde_tests.test_eeprom module +---------------------------------- + +.. automodule:: sonic_pde_tests.test_eeprom + :members: + :undoc-members: + :show-inheritance: + +sonic_pde_tests.test_fan module +------------------------------- + +.. automodule:: sonic_pde_tests.test_fan + :members: + :undoc-members: + :show-inheritance: + +sonic_pde_tests.test_leds module +-------------------------------- + +.. automodule:: sonic_pde_tests.test_leds + :members: + :undoc-members: + :show-inheritance: + +sonic_pde_tests.test_os module +------------------------------ + +.. automodule:: sonic_pde_tests.test_os + :members: + :undoc-members: + :show-inheritance: + +sonic_pde_tests.test_platform module +------------------------------------ + +.. automodule:: sonic_pde_tests.test_platform + :members: + :undoc-members: + :show-inheritance: + +sonic_pde_tests.test_port module +-------------------------------- + +.. automodule:: sonic_pde_tests.test_port + :members: + :undoc-members: + :show-inheritance: + +sonic_pde_tests.test_psu module +------------------------------- + +.. automodule:: sonic_pde_tests.test_psu + :members: + :undoc-members: + :show-inheritance: + +sonic_pde_tests.test_rtc module +------------------------------- + +.. automodule:: sonic_pde_tests.test_rtc + :members: + :undoc-members: + :show-inheritance: + +sonic_pde_tests.test_sfp module +------------------------------- + +.. automodule:: sonic_pde_tests.test_sfp + :members: + :undoc-members: + :show-inheritance: + +sonic_pde_tests.test_thermal module +----------------------------------- + +.. automodule:: sonic_pde_tests.test_thermal + :members: + :undoc-members: + :show-inheritance: + +sonic_pde_tests.test_usb module +------------------------------- + +.. automodule:: sonic_pde_tests.test_usb + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: sonic_pde_tests + :members: + :undoc-members: + :show-inheritance: diff --git a/sonic-pde-tests/setup.cfg b/sonic-pde-tests/setup.cfg new file mode 100644 index 0000000..e69de29 diff --git a/sonic-pde-tests/setup.py b/sonic-pde-tests/setup.py new file mode 100644 index 0000000..92c7780 --- /dev/null +++ b/sonic-pde-tests/setup.py @@ -0,0 +1,36 @@ +# https://github.com/ninjaaron/fast-entry_points +# workaround for slow 'pkg_resources' import +# +# NOTE: this only has effect on console_scripts and no speed-up for commands +# under scripts/. Consider stop using scripts and use console_scripts instead +# +# https://stackoverflow.com/questions/18787036/difference-between-entry-points-console-scripts-and-scripts-in-setup-py +try: + import fastentrypoints +except ImportError: + from setuptools.command import easy_install + import pkg_resources + easy_install.main(['fastentrypoints']) + pkg_resources.require('fastentrypoints') + import fastentrypoints + +import glob +from setuptools import setup + +setup( + name='sonic_pde_tests', + version='1.0', + description='PDE pytest runtime utilities for SONiC', + license='Apache 2.0', + author='Broadcom SONiC Team', + packages=[ + 'sonic_pde_tests', + ], + package_data={ + 'sonic_pde_tests': ['data/platform/*.json','data/template/*.json'] + }, + tests_require = [ + 'pytest' + ], + keywords='sonic PDE utilities', +) diff --git a/sonic-pde-tests/sonic_pde_tests/__init__.py b/sonic-pde-tests/sonic_pde_tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sonic-pde-tests/sonic_pde_tests/conftest.py b/sonic-pde-tests/sonic_pde_tests/conftest.py new file mode 100644 index 0000000..a061393 --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/conftest.py @@ -0,0 +1,61 @@ +import os +import pytest +import json +import subprocess + +def pytest_configure(config): + config.addinivalue_line("markers", "semiauto: this marks test will run in semiauto mode.") + +def pytest_addoption(parser): + parser.addoption( + "--semiauto", action="store_true", default=False, help="run semiautomated tests") + +def pytest_collection_modifyitems(config,items): + if config.getoption("--semiauto"): + return + skip_semiauto = pytest.mark.skip(reason="need --semiauto option to run") + for item in items: + if "semiauto" in item.keywords: + item.add_marker(skip_semiauto) + +# Get platform name from ONIE +def get_onie_pname(): + cmd = "cat /host/machine.conf | grep onie_platform | cut -d '=' -f 2" + pin = subprocess.Popen(cmd, + shell=True, + close_fds=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + id = pin.communicate()[0] + id = id.strip() + return id + + +@pytest.fixture(scope='function',autouse='True') +def json_config_data(): + """ Loads json file """ + INPUT_DIR = os.path.dirname(os.path.abspath(__file__)) + fname = os.path.join(INPUT_DIR, 'data/platform', "platform-" + get_onie_pname() + "-config.json") + try: + with open('/home/pde/platform-config.json') as file_object: + contents=json.load(file_object) + except: + with open(fname) as file_object: + contents=json.load(file_object) + + return contents + +@pytest.fixture(scope='function',autouse='True') +def json_test_data(): + """ Loads json file """ + INPUT_DIR = os.path.dirname(os.path.abspath(__file__)) + fname = os.path.join(INPUT_DIR, 'data/platform', "test-" + get_onie_pname() + "-config.json") + try: + with open('/home/pde/test-config.json') as file_object: + contents=json.load(file_object) + except: + with open(fname) as file_object: + contents=json.load(file_object) + + return contents + diff --git a/sonic-pde-tests/sonic_pde_tests/data/platform/platform-x86_64-accton_as7312_54x-r0-config.json b/sonic-pde-tests/sonic_pde_tests/data/platform/platform-x86_64-accton_as7312_54x-r0-config.json new file mode 100644 index 0000000..fcc5f58 --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/data/platform/platform-x86_64-accton_as7312_54x-r0-config.json @@ -0,0 +1,90 @@ +{ + "PLATFORM": { + "num_psus": 2, + "num_cplds": 3, + "num_syseeproms": 1, + "num_fans": 4, + "num_ports": 54, + "num_sfps": 6, + "num_temps": 3, + "num_serviceports": 1, + "serviceport": "eth0", + "modules" : { + "FAN": { + "support" : "true", + "path": "as7312_54x", + "name": "fanutil", + "class": "FanUtil" + }, + "TEMP": { + "support" : "true", + "path": "as7312_54x", + "name": "thermalutil", + "class": "ThermalUtil" + }, + "CPLD": { + "support": "false" + }, + "SYSLED": { + "support": "false" + } + }, + "drivers": { + "CPLD": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "accton_i2c_cpld" + } + }, + "PSU": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "accton_as7312_54x_psu" + } + }, + "FAN": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "accton_as7312_54x_fan" + } + }, + "SFP": { + "driver_info": { + "support": "false" + } + }, + "TEMP": { + "driver_info": { + "support": "true", + "type": "GENERIC", + "name": "lm75" + } + }, + "SYSLED": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "accton_as7312_54x_leds" + } + }, + "EEPROM": { + "driver_info": { + "support": "true", + "type": "GENERIC", + "name": "at24" + } + }, + "MAC": { + "driver_info": { + "support": "true", + "type": "GENERIC", + "name": "igb" + } + } + } + } +} + diff --git a/sonic-pde-tests/sonic_pde_tests/data/platform/platform-x86_64-accton_as7712_32x-r0-config.json b/sonic-pde-tests/sonic_pde_tests/data/platform/platform-x86_64-accton_as7712_32x-r0-config.json new file mode 100644 index 0000000..b52c84d --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/data/platform/platform-x86_64-accton_as7712_32x-r0-config.json @@ -0,0 +1,90 @@ +{ + "PLATFORM": { + "num_psus": 2, + "num_cplds": 3, + "num_syseeproms": 1, + "num_fans": 6, + "num_ports": 32, + "num_sfps": 32, + "num_temps": 3, + "num_serviceports": 1, + "serviceport": "eth0", + "modules" : { + "FAN": { + "support" : "true", + "path": "as7312_54x", + "name": "fanutil", + "class": "FanUtil" + }, + "TEMP": { + "support" : "true", + "path": "as7312_54x", + "name": "thermalutil", + "class": "ThermalUtil" + }, + "CPLD": { + "support": "false" + }, + "SYSLED": { + "support": "false" + } + }, + "drivers": { + "CPLD": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "accton_i2c_cpld" + } + }, + "PSU": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "accton_as7712_32x_psu" + } + }, + "FAN": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "accton_as7712_32x_fan" + } + }, + "SFP": { + "driver_info": { + "support": "false" + } + }, + "TEMP": { + "driver_info": { + "support": "true", + "type": "GENERIC", + "name": "lm75" + } + }, + "SYSLED": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "leds_accton_as7712_32x" + } + }, + "EEPROM": { + "driver_info": { + "support": "true", + "type": "GENERIC", + "name": "at24" + } + }, + "MAC": { + "driver_info": { + "support": "true", + "type": "GENERIC", + "name": "igb" + } + } + } + } +} + diff --git a/sonic-pde-tests/sonic_pde_tests/data/platform/platform-x86_64-accton_as7816_64x-r0-config.json b/sonic-pde-tests/sonic_pde_tests/data/platform/platform-x86_64-accton_as7816_64x-r0-config.json new file mode 100644 index 0000000..ff5939a --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/data/platform/platform-x86_64-accton_as7816_64x-r0-config.json @@ -0,0 +1,98 @@ +{ + "PLATFORM": { + "num_psus": 2, + "num_cplds": 2, + "num_syseeproms": 1, + "num_fans": 4, + "num_ports": 54, + "num_sfps": 64, + "num_temps": 6, + "num_serviceports": 1, + "serviceport": "eth0", + "modules" : { + "FAN": { + "support": "true", + "path": "as7816_64x", + "name": "fanutil.py", + "class": "FanUtil" + }, + "TEMP": { + "support": "true", + "path": "as7816_64x", + "name": "thermalutil", + "class": "ThermalUtil" + }, + "CPLD": { + "support": "true", + "path": "as7816_64x", + "name": "cpldutil", + "class" : "CpldUtil" + }, + "SYSLED": { + "support": "true", + "path": "as7816_64x", + "name": "ledutil", + "class": "LedUtil" + } + }, + "drivers": { + "CPLD": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "accton_i2c_cpld" + } + }, + "PSU": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "as7816_64x_psu" + } + }, + "FAN": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "as7816_64x_fan" + } + }, + "SFP": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "as7816_64x_sfp" + } + }, + "TEMP": { + "driver_info": { + "support": "true", + "type": "GENERIC", + "name": "lm75" + } + }, + "SYSLED": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "as7816_64x_leds" + } + }, + "EEPROM": { + "driver_info": { + "support": "true", + "type": "GENERIC", + "name": "at24" + } + }, + "MAC": { + "driver_info": { + "support": "true", + "type": "GENERIC", + "name": "igb" + } + } + } + } +} + diff --git a/sonic-pde-tests/sonic_pde_tests/data/platform/platform-x86_64-quanta_ix8_rglbmc-r0-config.json b/sonic-pde-tests/sonic_pde_tests/data/platform/platform-x86_64-quanta_ix8_rglbmc-r0-config.json new file mode 100644 index 0000000..f3a499f --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/data/platform/platform-x86_64-quanta_ix8_rglbmc-r0-config.json @@ -0,0 +1,78 @@ +{ + "PLATFORM": { + "num_psus": 2, + "num_cplds": 0, + "num_syseeproms": 1, + "num_fans": 0, + "num_ports": 56, + "num_sfps": 56, + "num_temps": 0, + "num_serviceports": 1, + "serviceport": "eth0", + "modules" : { + "FAN": { + "support": "false" + }, + "TEMP": { + "support": "false" + }, + "CPLD": { + "support": "false" + }, + "SYSLED": { + "support": "false" + } + }, + "drivers": { + "CPLD": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "qci_platform_ix8" + } + }, + "PSU": { + "driver_info": { + "support": "false" + } + }, + "FAN": { + "driver_info": { + "support": "false" + } + }, + "SFP": { + "driver_info": { + "support": "false" + } + }, + "TEMP": { + "driver_info": { + "support": "false" + } + }, + "SYSLED": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "qci_cpld_led" + } + }, + "EEPROM": { + "driver_info": { + "support": "true", + "type": "GENERIC", + "name": "at24" + } + }, + "MAC": { + "driver_info": { + "support": "true", + "type": "GENERIC", + "name": "igb" + } + } + } + } +} + diff --git a/sonic-pde-tests/sonic_pde_tests/data/platform/test-x86_64-accton_as7312_54x-r0-config.json b/sonic-pde-tests/sonic_pde_tests/data/platform/test-x86_64-accton_as7312_54x-r0-config.json new file mode 100644 index 0000000..aa29664 --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/data/platform/test-x86_64-accton_as7312_54x-r0-config.json @@ -0,0 +1,134 @@ +{ + "PLATFORM": { + "powercontrol": true, + "PSU": { + "present": [ + 1, + 2 + ], + "PSU1": { + "psu_serial_num": "AAAA" + }, + "PSU2": { + "psu_serial_num": "BBBB" + } + }, + "SFP": { + "present": [ + 6, + 9, + 15, + 24, + 36, + 39, + 48, + 56, + 64, + 68, + 72 + ] + }, + "USB": { + "enable": "yes", + "device": "sdb", + "mountpoint": "/media/usb-storage" + }, + "EEPROM": { + "mac": "00:11:22:33:44:55", + "ser": "AABBCCDDEEFF", + "model": "AAAA" + }, + "CPLD": { + "CPLD1": { + "version": "2" + }, + "CPLD2": { + "version": "1" + } + }, + "FAN": { + "present": [ + 1, + 2, + 3, + 4 + ], + "FAN1": { + "direction": 0 + }, + "FAN2": { + "direction": 0 + }, + "FAN3": { + "direction": 0 + }, + "FAN4": { + "direction": 0 + } + }, + "MAC": + { + "MAC1":{ + "ifname": "eth0", + "macaddr": "XX:XX:XX:XX:XX:XX" + } + }, + "SYSLED": + { + "FANTRAY":{ + "FANTRAY1":{ + "color":"GREEN", + "state" : "SOLID" + }, + "FANTRAY2":{ + "color":"GREEN", + "state" : "SOLID" + }, + "FANTRAY3":{ + "color":"GREEN", + "state" : "SOLID" + }, + "FANTRAY4":{ + "color":"GREEN", + "state" : "SOLID" + } + }, + "PSU":{ + "PSU1":{ + "color":"GREEN", + "state" : "SOLID" + }, + "PSU2":{ + "color":"GREEN", + "state" : "SOLID" + } + }, + "FAN":{ + "color":"GREEN", + "state" : "SOLID" + }, + "SYS":{ + "color":"GREEN", + "state" : "SOLID" + }, + "LOC":{ + "color":"GREEN", + "state" : "SOLID" + } + }, + "OS": + { + "flooding": { + "dmesg": [ + "error" + ], + "syslog": [ + "i2c", + "usb", + "pci" + ] + } + } + + } +} diff --git a/sonic-pde-tests/sonic_pde_tests/data/platform/test-x86_64-accton_as7712_32x-r0-config.json b/sonic-pde-tests/sonic_pde_tests/data/platform/test-x86_64-accton_as7712_32x-r0-config.json new file mode 100644 index 0000000..910ebcd --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/data/platform/test-x86_64-accton_as7712_32x-r0-config.json @@ -0,0 +1,146 @@ +{ + "PLATFORM": { + "powercontrol": false, + "PSU": { + "present": [ + 1, + 2 + ], + "status": [ + "True", + "False" + ], + "PSU1": { + "psu_serial_num": "AAAA" + }, + "PSU2": { + "psu_serial_num": "BBBB" + } + }, + "SFP": { + "present": [ + 13, + 17, + 52, + 68 + ] + }, + "USB": { + "enable": "yes", + "device": "sdb", + "mountpoint": "/media/usb-storage" + }, + "EEPROM": { + "mac": "3c:2c:99:2e:d9:75", + "ser": "771232X1752003", + "model": "7712-32X-O-AC-F" + }, + "CPLD": { + "CPLD1": { + "version": "2" + }, + "CPLD2": { + "version": "1" + } + }, + "FAN": { + "present": [ + 1, + 2, + 3, + 4, + 5, + 6 + ], + "FAN1": { + "direction": 0 + }, + "FAN2": { + "direction": 0 + }, + "FAN3": { + "direction": 0 + }, + "FAN4": { + "direction": 0 + }, + "FAN5": { + "direction": 0 + }, + "FAN6": { + "direction": 0 + } + }, + "MAC": + { + "MAC1":{ + "ifname": "eth0", + "macaddr": "3c:2c:99:2e:d9:75" + } + }, + "SYSLED": + { + "FANTRAY":{ + "FANTRAY1":{ + "color":"GREEN", + "state" : "SOLID" + }, + "FANTRAY2":{ + "color":"GREEN", + "state" : "SOLID" + }, + "FANTRAY3":{ + "color":"GREEN", + "state" : "SOLID" + }, + "FANTRAY4":{ + "color":"GREEN", + "state" : "SOLID" + } + }, + "PSU":{ + "PSU1":{ + "color":"GREEN", + "state" : "SOLID" + }, + "PSU2":{ + "color":"GREEN", + "state" : "SOLID" + } + }, + "FAN":{ + "color":"GREEN", + "state" : "SOLID" + }, + "SYS":{ + "color":"GREEN", + "state" : "SOLID" + }, + "LOC":{ + "color":"GREEN", + "state" : "SOLID" + } + }, + "OS": + { + "flooding": { + "dmesg": [ + "error" + ], + "syslog": [ + "i2c", + "usb", + "pci" + ] + } + }, + "CONFIG": + { + "required": { + "config.bcm": [ + "parity_enable=1" + ] + } + } + } +} diff --git a/sonic-pde-tests/sonic_pde_tests/data/platform/test-x86_64-accton_as7816_64x-r0-config.json b/sonic-pde-tests/sonic_pde_tests/data/platform/test-x86_64-accton_as7816_64x-r0-config.json new file mode 100644 index 0000000..37212ab --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/data/platform/test-x86_64-accton_as7816_64x-r0-config.json @@ -0,0 +1,133 @@ +{ + "PLATFORM": { + "powercontrol": true, + "PSU": { + "present": [ + 1, + 2 + ], + "PSU1": { + "psu_serial_num": "AAAA" + }, + "PSU2": { + "psu_serial_num": "BBBB" + } + }, + "SFP": { + "present": [ + 6, + 9, + 15, + 24, + 36, + 39, + 48, + 56, + 64, + 68, + 72 + ] + }, + "USB": { + "enable": "yes", + "device": "sdb", + "mountpoint": "/media/usb-storage" + }, + "EEPROM": { + "mac": "00:11:22:33:44:55", + "ser": "AABBCCDDEEFF", + "model": "AAAA" + }, + "CPLD": { + "CPLD1": { + "version": "2" + }, + "CPLD2": { + "version": "1" + } + }, + "FAN": { + "present": [ + 1, + 2, + 3, + 4 + ], + "FAN1": { + "direction": 0 + }, + "FAN2": { + "direction": 0 + }, + "FAN3": { + "direction": 0 + }, + "FAN4": { + "direction": 0 + } + }, + "MAC": + { + "MAC1":{ + "ifname": "eth0", + "macaddr": "XX:XX:XX:XX:XX:XX" + } + }, + "SYSLED": + { + "FANTRAY":{ + "FANTRAY1":{ + "color":"GREEN", + "state" : "SOLID" + }, + "FANTRAY2":{ + "color":"GREEN", + "state" : "SOLID" + }, + "FANTRAY3":{ + "color":"GREEN", + "state" : "SOLID" + }, + "FANTRAY4":{ + "color":"GREEN", + "state" : "SOLID" + } + }, + "PSU":{ + "PSU1":{ + "color":"GREEN", + "state" : "SOLID" + }, + "PSU2":{ + "color":"GREEN", + "state" : "SOLID" + } + }, + "FAN":{ + "color":"GREEN", + "state" : "SOLID" + }, + "SYS":{ + "color":"GREEN", + "state" : "SOLID" + }, + "LOC":{ + "color":"GREEN", + "state" : "SOLID" + } + }, + "OS": + { + "flooding": { + "dmesg": [ + "error" + ], + "syslog": [ + "i2c", + "usb", + "pci" + ] + } + } + } +} diff --git a/sonic-pde-tests/sonic_pde_tests/data/platform/test-x86_64-quanta_ix8_rglbmc-r0-config.json b/sonic-pde-tests/sonic_pde_tests/data/platform/test-x86_64-quanta_ix8_rglbmc-r0-config.json new file mode 100644 index 0000000..2ff560f --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/data/platform/test-x86_64-quanta_ix8_rglbmc-r0-config.json @@ -0,0 +1,111 @@ +{ + "PLATFORM": { + "powercontrol": false, + "PSU": { + "present": [ + 1, + 2 + ], + "status": [ + "True", + "True" + ], + "PSU1": { + "psu_serial_num": "AAAA" + }, + "PSU2": { + "psu_serial_num": "BBBB" + } + }, + "SFP": { + "present": [ + 0, + 1, + 48, + 49 + ] + }, + "USB": { + "enable": "yes", + "device": "sdb", + "mountpoint": "/media/usb-storage" + }, + "EEPROM": { + "mac": "d8:c4:97:28:30:a8", + "ser": "QTFCU38030006", + "model": "T4048-IX8" + }, + "MAC": + { + "MAC1":{ + "ifname": "eth0", + "macaddr": "54:ab:3a:9c:17:e5" + } + }, + "SYSLED": + { + "FAN":{ + "color":"Green", + "state" : "SOLID" + }, + "SYS":{ + "color":"Green", + "state" : "SOLID" + }, + "LOC":{ + "color":"Green", + "state" : "SOLID" + } + }, + "OS": + { + "flooding": { + "dmesg": [ + "error" + ], + "syslog": [ + "i2c", + "usb", + "pci" + ] + } + }, + "CONFIG": + { + "required": { + "config.bcm": [ + "parity_enable=1" + ] + } + }, + "TRAFFIC": + { + "port_pairs":[ + { + "src_front_portnum":"1", + "src_logical_portnum":"xe0", + "dst_front_portnum":"2", + "dst_logical_portnum":"xe1" + }, + { + "src_front_portnum":"2", + "src_logical_portnum":"xe1", + "dst_front_portnum":"1", + "dst_logical_portnum":"xe0" + }, + { + "src_front_portnum":"49", + "src_logical_portnum":"ce3", + "dst_front_portnum":"50", + "dst_logical_portnum":"ce4" + }, + { + "src_front_portnum":"50", + "src_logical_portnum":"ce4", + "dst_front_portnum":"49", + "dst_logical_portnum":"ce3" + } + ] + } + } +} diff --git a/sonic-pde-tests/sonic_pde_tests/data/template/platform-config.json b/sonic-pde-tests/sonic_pde_tests/data/template/platform-config.json new file mode 100644 index 0000000..91bd137 --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/data/template/platform-config.json @@ -0,0 +1,97 @@ +{ + "PLATFORM": { + "num_psus": 0, + "num_cplds": 0, + "num_syseeproms": 0, + "num_fans": 0, + "num_ports": 0, + "num_temps": 0, + "num_serviceports": 0, + "serviceport": "eth0", + "modules" : { + "FAN": { + "support" : "true/false", + "path": "XXXX", + "name": "XXXX", + "class": "XXXX" + }, + "CPLD" : { + "support" : "true/false", + "path" :"XXXX", + "name" :"XXXX", + "class" : "XXXX" + }, + "SYSLED" : { + "support" : "true/false", + "path" :"XXXX", + "name" :"XXXX", + "class" : "XXXX" + }, + "TEMP" : { + "support" : "true/false", + "path" :"XXXX", + "name" :"XXXX", + "class" : "XXXX" + } + }, + "drivers": { + "CPLD": { + "driver_info": { + "support": "true/false", + "type": "ODM/GENERIC/PDDF", + "name": "xxxx" + } + }, + "PSU": { + "driver_info": { + "support": "true/false", + "type": "ODM/GENERIC/PDDF", + "name": "xxxx" + } + }, + "FAN": { + "driver_info": { + "support": "true/false", + "type": "ODM/GENERIC/PDDF", + "name": "xxxx" + } + }, + "SFP": { + "driver_info": { + "support": "true/false", + "type": "ODM/GENERIC/PDDF", + "name": "xxxx" + } + }, + "TEMP": { + "driver_info": { + "support": "true/false", + "type": "ODM/GENERIC/PDDF", + "name": "xxxx" + } + }, + "SYSLED": { + "driver_info": { + "support": "true/false", + "type": "ODM/GENERIC/PDDF", + "name": "xxxx" + } + }, + "EEPROM": { + "driver_info": { + "support": "true/false", + "type": "ODM/GENERIC/PDDF", + "name": "xxxx" + } + }, + "MAC" : { + "driver_info": { + "support": "true/false", + "type": "ODM/GENERIC/PDDF", + "name": "xxxx" + } + } + } + } +} + diff --git a/sonic-pde-tests/sonic_pde_tests/data/template/test-config.json b/sonic-pde-tests/sonic_pde_tests/data/template/test-config.json new file mode 100644 index 0000000..030862f --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/data/template/test-config.json @@ -0,0 +1,152 @@ +{ + "PLATFORM": { + "powercontrol": "TRUE/FALSE", + "PSU": { + "present": [ + 1, + 2 + ], + "PSU#X": { + "psu_serial_num": "XXXX" + }, + "PSU#X+1": { + "psu_serial_num": "XXXX" + } + }, + "SFP": { + "present": [ + 1, + 3, + 5, + 7 + ], + "SFP#X": { + "lpmode": "ON/OFF" + } + }, + "EEPROM": { + "mac": "XX:XX:XX:XX:XX:XX", + "ser": "XXXXXXXXXX", + "model": "XXXXXXXX" + }, + "CPLD": { + "CPLD#X": { + "version": "XX" + }, + "CPLD#X+1": { + "version": "XX" + }, + "CPLD#X+2": { + "version": "XX" + } + }, + "FAN": { + "present": [ + 1, + 2 + ], + "FAN#X": { + "direction": "0/1" + }, + "FAN#X+1": { + "direction": "0/1" + } + }, + "USB": { + "enable": "yes/no", + "device": "sd#X", + "mountpoint": "/xxxx/xxxxxxx" + }, + "MAC": { + "MAC#X": { + "ifname": "XXX", + "macaddr": "XX:XX:XX:XX:XX:XX" + } + }, + "SYSLED": + { + "FANTRAY":{ + "FANTRAY1":{ + "color":"GREEN/RED/AMBER", + "state" : "SOLID/BLINKING" + }, + "FANTRAY2":{ + "color":"GREEN/RED/AMBER", + "state" : "SOLID/BLINKING" + } + }, + "PSU":{ + "PSU1":{ + "color":"GREEN/RED/AMBER", + "state" : "SOLID/BLINKING" + }, + "PSU2":{ + "color":"GREEN/RED/AMBER", + "state" : "SOLID/BLINKING" + } + }, + "FAN":{ + "color":"GREEN/RED/AMBER", + "state" : "SOLID/BLINKING" + }, + "SYS":{ + "color":"GREEN/RED/AMBER", + "state" : "SOLID/BLINKING" + }, + "LOC":{ + "color":"GREEN/RED/AMBER", + "state" : "SOLID/BLINKING" + } + }, + "OS": + { + "flooding": { + "dmesg": [ + "error" + ], + "syslog": [ + "i2c", + "usb", + "pci" + ] + } + }, + "CONFIG": + { + "required": { + "config.bcm": [ + "parity_enable=1" + ] + } + } + "TRAFFIC": + { + "port_pairs":[ + { + "src_front_portnum":"1", + "src_logical_portnum":"xe0", + "dst_front_portnum":"2", + "dst_logical_portnum":"xe1" + }, + { + "src_front_portnum":"2", + "src_logical_portnum":"xe1", + "dst_front_portnum":"1", + "dst_logical_portnum":"xe0" + }, + { + "src_front_portnum":"49", + "src_logical_portnum":"ce3", + "dst_front_portnum":"50", + "dst_logical_portnum":"ce4" + }, + { + "src_front_portnum":"50", + "src_logical_portnum":"ce4", + "dst_front_portnum":"49", + "dst_logical_portnum":"ce3" + } + ] + } + } +} diff --git a/sonic-pde-tests/sonic_pde_tests/test_bmc.py b/sonic-pde-tests/sonic_pde_tests/test_bmc.py new file mode 100644 index 0000000..84bd29e --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/test_bmc.py @@ -0,0 +1,11 @@ +import pytest +import sys +import imp + + +def test_for_bmc(json_config_data): + pytest.skip("Not supported") + +if __name__ == '__main__': + unittest.main() + diff --git a/sonic-pde-tests/sonic_pde_tests/test_config.py b/sonic-pde-tests/sonic_pde_tests/test_config.py new file mode 100644 index 0000000..ef98d44 --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/test_config.py @@ -0,0 +1,73 @@ +#!/usr/bin/python + +try: + import pytest + import json + import time + import os + import sys + import subprocess +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +def test_for_required_bcm_config_file(json_test_data): + """ Test Purpose: Verify the SAI config.bcm file (sai.profile) is present. + + Args: + arg1 (json): test--config.json + + Example: + No test or platform JSON changes necesssary. + """ + + with open('/etc/sai.d/sai.profile') as data: + for line in data: + if line.find("SAI_PROFILE") == -1: + contents = line.strip().split("=") + config_file = contents[1] + + assert config_file != {}, "Chipset configuration file not found" + +def test_for_required_bcm_config_settings(json_test_data): + """Test Purpose: Verify that the platform config.bcm file contains mandatory Silicon supported features. + + Args: + arg1 (json): test--config.json + + Example: + Parity should always be enabled for Broadcom switching silicon. + + "PLATFORM": { + "CONFIG": { + "required": { + "config.bcm": [ + "parity_enable=1" + ] + } + } + """ + + with open('/etc/sai.d/sai.profile') as data: + for line in data: + if line.find("SAI_PROFILE") == -1: + contents = line.strip().split("=") + config_file = contents[1] + + assert config_file != {}, "Chipset configuration file not found" + + pat = json_test_data["PLATFORM"]["CONFIG"]["required"]["config.bcm"] + # sampling pattern counts - start point + for idx in range(len(pat)): + cmd = "cat " + config_file + " | grep -c -i " + pat[idx] + pin = subprocess.Popen(cmd, + shell=True, + close_fds=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + cnt = pin.communicate()[0] + print cnt + + assert int(cnt)==1, "Required configuration property [" + pat[idx] + "] not detected" + + + diff --git a/sonic-pde-tests/sonic_pde_tests/test_cpld.py b/sonic-pde-tests/sonic_pde_tests/test_cpld.py new file mode 100644 index 0000000..9cf3fc3 --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/test_cpld.py @@ -0,0 +1,90 @@ +import pytest +import sys +import imp +import subprocess +import time + + +# Global platform-specific cpldutil class instance +platform_cpldutil = None + +# Loads platform specific cpldutil module from source +def load_platform_cpldutil(json_config_data): + global platform_cpldutil + + if platform_cpldutil is not None: + return + + try: + if json_config_data['PLATFORM']['modules']['CPLD']['support'] == "false": + pytest.skip("Skip the testing due to the module is not supported in BSP") + + modules_dir = json_config_data['PLATFORM']['modules']['CPLD']['path'] + modules_name = json_config_data['PLATFORM']['modules']['CPLD']['name'] + class_name = json_config_data['PLATFORM']['modules']['CPLD']['class'] + cpld_module = "/usr/share/sonic/classes/" + modules_dir + "/" + modules_name + '.py' + platform_cpldutil_module = imp.load_source(modules_name,cpld_module) + platform_cpldutil_class = getattr(platform_cpldutil_module,class_name) + platform_cpldutil = platform_cpldutil_class() + + except AttributeError, e: + print("Failed to instantiate '%s' class: %s" % (class_name, str(e)), True) + + return + + +def test_for_num_cpld(json_config_data): + """Test Purpose: Verify that the numer of CPLD reported as supported + by the CPLD plugin matches what the platform supports + + Args: + arg1 (json): platform--config.json + + Example: + For a system that physically supports 2 CPLD + + platform--config.json + { + "PLATFORM": { + "num_cplds": 2 + } + } + """ + + load_platform_cpldutil(json_config_data) + assert platform_cpldutil.get_num_cplds() == json_config_data['PLATFORM']['num_cplds'],\ + "verify CPLD numbers {} not matching with platform JSON".format(platform_cpldutil.get_num_cplds()) + +def test_for_cpld_read(json_config_data,json_test_data): + """Test Purpose: Test Purpose: Verify that the CPLD version able to read and value + is matching with the value defined in test config JSON + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + For a system that physically supports 2 CPLD, the CPLD version defined in the + test--config.json + + "CPLD": { + "CPLD1": { + "version": "2" + }, + "CPLD2": { + "version": "1" + } + }, + + + """ + + load_platform_cpldutil(json_config_data) + for key in json_config_data: + for x in range(json_config_data[key]['num_cplds']): + assert platform_cpldutil.get_cpld_version(x+1).strip() == json_test_data[key]['CPLD']['CPLD'+str(x+1)]['version'], \ + "verify" + " CPLD"+str(x+1)+" version={} is False".format(platform_cpldutil.get_cpld_version(x+1)) + +if __name__ == '__main__': + unittest.main() + diff --git a/sonic-pde-tests/sonic_pde_tests/test_eeprom.py b/sonic-pde-tests/sonic_pde_tests/test_eeprom.py new file mode 100644 index 0000000..ee9b4fc --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/test_eeprom.py @@ -0,0 +1,130 @@ +import pytest +import sys +import imp +import subprocess +import time + +PLATFORM_SPECIFIC_CLASS_NAME = "board" + +def test_for_eeprom_read(): + """Test Purpose: Verify that the EEPROM read is ok and chcksum is valid + """ + + module = imp.load_source("eeprom","/usr/share/sonic/platform/plugins/eeprom.py") + board = getattr(module, PLATFORM_SPECIFIC_CLASS_NAME) + eeprom = board('',0,'',True) + assert eeprom.is_checksum_valid(eeprom.read_eeprom()),\ + "verify checksum is invalid".format(eeprom.read_eeprom()) + + +def test_for_eeprom_mac(json_config_data,json_test_data): + """Test Purpose: Verify that the MAC read from EEPROM is matching with the + test config JSON setting + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + For a system that physically supports 1 syseeprom, the MAC address is + configured in the test--config.json + + test--config.json + "EEPROM": { + "mac": "00:11:22:33:44:55", + "ser": "AABBCCDDEEFF", + "model": "AAAA" + }, + """ + + module = imp.load_source("eeprom","/usr/share/sonic/platform/plugins/eeprom.py") + board = getattr(module, PLATFORM_SPECIFIC_CLASS_NAME) + eeprom = board('',0,'',True) + for key in json_config_data: + assert eeprom.base_mac_addr(eeprom.read_eeprom()) == json_test_data[key]['EEPROM']['mac'],\ + "verify MAC is invalid".format(eeprom.read_eeprom()) + + +def test_for_eeprom_SER(json_config_data,json_test_data): + """Test Purpose: Verify that the SERIAL read from EEPROM is matching with the + test config JSON setting + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + For a system that physically supports 1 syseeprom, the SERIAL number is + configured in the test--config.json + + test--config.json + "EEPROM": { + "mac": "00:11:22:33:44:55", + "ser": "AABBCCDDEEFF", + "model": "AAAA" + }, + """ + + module = imp.load_source("eeprom","/usr/share/sonic/platform/plugins/eeprom.py") + board = getattr(module, PLATFORM_SPECIFIC_CLASS_NAME) + eeprom = board('',0,'',True) + + for key in json_config_data: + assert eeprom.serial_number_str(eeprom.read_eeprom()) == json_test_data[key]['EEPROM']['ser'],\ + "verify SER NUMBER is invalid".format(eeprom.read_eeprom()) + + +def test_for_eeprom_MODEL(json_config_data,json_test_data): + """Test Purpose: Verify that the MODEL read from EEPROM is matching with the + test config JSON setting + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + For a system that physically supports 1 syseeprom, the MODEL is + configured in the test--config.json + + test--config.json + "EEPROM": { + "mac": "00:11:22:33:44:55", + "ser": "AABBCCDDEEFF", + "model": "AAAA" + }, + """ + module = imp.load_source("eeprom","/usr/share/sonic/platform/plugins/eeprom.py") + board = getattr(module, PLATFORM_SPECIFIC_CLASS_NAME) + eeprom = board('',0,'',True) + + for key in json_config_data: + assert eeprom.modelstr(eeprom.read_eeprom()) == json_test_data[key]['EEPROM']['model'],\ + "verify Model Name is invalid".format(eeprom.read_eeprom()) + + +def test_for_platform_id(json_config_data,json_test_data): + module = imp.load_source("eeprom","/usr/share/sonic/platform/plugins/eeprom.py") + board = getattr(module, PLATFORM_SPECIFIC_CLASS_NAME) + eeprom = board('',0,'',True) + + valid, t = eeprom.get_tlv_field(eeprom.read_eeprom(), \ + eeprom._TLV_CODE_PLATFORM_NAME) + assert valid, "Unable to get platform name from EEPROM" + + cmd = "cat /host/machine.conf | grep onie_platform | cut -d '=' -f 2" + pin = subprocess.Popen(cmd, + shell=True, + close_fds=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + id = pin.communicate()[0] + id = id.strip() + assert id == t[2], "platform id mismatch" + return + + + + +if __name__ == '__main__': + unittest.main() + diff --git a/sonic-pde-tests/sonic_pde_tests/test_fan.py b/sonic-pde-tests/sonic_pde_tests/test_fan.py new file mode 100644 index 0000000..d04262b --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/test_fan.py @@ -0,0 +1,207 @@ +import pytest +import sys +import imp +import subprocess +import time + +DUTY_MAX = 100 + + +# Global platform-specific fanutil class instance +platform_fanutil = None + +# Loads platform specific fanutil module from source +def load_platform_fanutil(json_config_data): + global platform_fanutil + + if platform_fanutil is not None: + return + + try: + if json_config_data['PLATFORM']['modules']['FAN']['support'] == "false": + pytest.skip("Skip the testing due to the python module is not supported in BSP") + + modules_dir = json_config_data['PLATFORM']['modules']['FAN']['path'] + modules_name = json_config_data['PLATFORM']['modules']['FAN']['name'] + class_name = json_config_data['PLATFORM']['modules']['FAN']['class'] + module_fan = "/usr/share/sonic/classes/" + modules_dir + "/" + modules_name + '.py' + module = imp.load_source(modules_name, module_fan) + platform_fanutil_class = getattr(module,class_name) + platform_fanutil = platform_fanutil_class() + + except AttributeError, e: + print("Failed to instantiate '%s' class: %s" % (class_name, str(e)), True) + + return + + +def test_for_num_fans(json_config_data): + """Test Purpose: Verify that the numer of FANs reported as supported + by the FAN plugin matches what the platform supports + + Args: + arg1 (json): platform--config.json + + Example: + For a system that physically supports 4 FAN + + platform--config.json + { + "PLATFORM": { + "num_fans": 4 + } + } + """ + + load_platform_fanutil(json_config_data) + + assert platform_fanutil.get_num_fans() == json_config_data['PLATFORM']['num_fans'],\ + "verify FAN numbers = {} not matching with platform JSON".format(platform_fanutil.get_num_fans()) + +@pytest.mark.semiauto +def test_for_fans_dir(json_config_data,json_test_data): + """Test Purpose: Verify that the FAN direction reported as supported + by the FAN plugin matches with test config JSON + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + Test config JSON setting for FAN direction + + "FAN": { + "FAN1": { + "direction": 0 + }, + "FAN2": { + "direction": 0 + }, + "FAN3": { + "direction": 0 + }, + "FAN4": { + "direction": 0 + } + } + """ + load_platform_fanutil(json_config_data) + + for key in json_config_data: + for x in json_test_data[key]['FAN']['present']: + assert platform_fanutil.get_fan_dir(x) == json_test_data[key]['FAN']['FAN'+str(x)]['direction'],\ + "verify FAN"+str(x)+" DIR = {} is invalid".format(platform_fanutil.get_fan_dir(x)) + +def test_for_fans_status(json_config_data,json_test_data): + + """Test Purpose: Verify that the FAN status of each present FAN + reported as supported by the FAN plugin matches + with test config JSON + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + Test config JSON setting for FAN direction + + "FAN": { + "present": [ + 1, + 2, + 3, + 4 + ], + }, + """ + + load_platform_fanutil(json_config_data) + + for key in json_config_data: + for x in json_test_data[key]['FAN']['present']: + assert platform_fanutil.get_fan_status(x) == True,\ + "verify FAN"+str(x)+" status = {} is False".format(platform_fanutil.get_fan_status(x)) + + +def test_for_fans_present(json_config_data,json_test_data): + load_platform_fanutil(json_config_data) + + """Test Purpose: Verify that the FAN present reported as supported by the + FAN plugin matches with test config JSON + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + Test config JSON setting for FAN present + + "FAN": { + "present": [ + 1, + 2, + 3, + 4 + ], + }, + """ + + + for key in json_config_data: + list = json_test_data[key]['FAN']['present'] + for x in range(json_config_data['PLATFORM']['num_fans']): + if x in list: + assert platform_fanutil.get_fan_status(x) == True,\ + "FAN"+str(x)+" is not present, status = {}".format(platform_fanutil.get_fan_status(x)) + else: + assert platform_fanutil.get_fan_status(x) == None,\ + "FAN"+str(x)+" is present, status = {}".format(platform_fanutil.get_fan_status(x)) + + +def test_for_fans_duty(json_config_data): + """Test Purpose:Verify that the FAN Duty Get and Set is working fine by using the FAN module + defined in platform config JSON + + args: + arg1 (json): platform--config.json + + example: + Platform config JSON for FAN modules support + + platform--config.json + { + "modules" : { + "FAN": { + "support" : "true/false", + "path": "XXXX", + "name": "XXXX", + "class": "XXXX" + }, + } + } + + """ + + load_platform_fanutil(json_config_data) + + old_duty = platform_fanutil.get_fan_duty_cycle() + new_duty = old_duty + platform_fanutil.set_fan_duty_cycle(DUTY_MAX) + timeout = 0 + + while( new_duty < DUTY_MAX ): + time.sleep(1) + new_duty = platform_fanutil.get_fan_duty_cycle() + timeout = timeout+1 + if timeout > 10: + break + + assert platform_fanutil.get_fan_duty_cycle() == DUTY_MAX,\ + "verify changging FAN Duty to MAX is False".format(platform_fanutil.get_fan_duty_cycle()) + + platform_fanutil.set_fan_duty_cycle(old_duty) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sonic-pde-tests/sonic_pde_tests/test_leds.py b/sonic-pde-tests/sonic_pde_tests/test_leds.py new file mode 100644 index 0000000..929fe7b --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/test_leds.py @@ -0,0 +1,217 @@ +import pytest +import sys +import imp +import subprocess +import time + + +# Global platform-specific sysledutil class instance +platform_sysledutil = None + +# Loads platform specific sysledutil module from source +def load_platform_sysledutil(json_config_data): + global platform_sysledutil + + if platform_sysledutil is not None: + return + + try: + + if json_config_data['PLATFORM']['modules']['SYSLED']['support'] == "false": + pytest.skip("Skip the testing due to the python module is not supported") + + modules_dir = json_config_data['PLATFORM']['modules']['SYSLED']['path'] + modules_name = json_config_data['PLATFORM']['modules']['SYSLED']['name'] + class_name = json_config_data['PLATFORM']['modules']['SYSLED']['class'] + sysledutil_module = "/usr/share/sonic/classes/" + modules_dir + "/" + modules_name + '.py' + platform_sysledutil_module = imp.load_source(modules_name,sysledutil_module) + platform_sysledutil_class = getattr(platform_sysledutil_module,class_name) + platform_sysledutil = platform_sysledutil_class() + + except AttributeError, e: + print("Failed to instantiate '%s' class: %s" % (class_name, str(e)), True) + + return + + +def test_for_set_fan_sysled(json_config_data, json_test_data): + + """Test Purpose: Verify that the SYS FAN LED is able to set per the color and state + defined in the test config JSON + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + SYSLED Color state setting for the FAN defined in JSON + configured in the test--config.json + + "SYSLED": + { + "FAN":{ + "color":"GREEN/RED/AMBER", + "state" : "SOLID/BLINKING" + }, + + """ + + load_platform_sysledutil(json_config_data) + for key in json_config_data: + color = json_test_data[key]['SYSLED']['FAN']['color'] + state = json_test_data[key]['SYSLED']['FAN']['state'] + index = 0 + platform_sysledutil.set_status_led('fan', index, color, state) + + assert platform_sysledutil.get_status_led('fan', index) == state,\ + "fan"+str(index)+" sys led color is fail to changed, status = {}".format(get_status_led('fan', index)) + +def test_for_set_fantray_sysled(json_config_data, json_test_data): + + """Test Purpose: Verify that the SYS FANTRAY LED is able to set per the color and state + defined in the test config JSON + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + SYSLED Color state setting for the FANTRAY defined in JSON + configured in the test--config.json + + + "SYSLED": + { + "FANTRAY":{ + "FANTRAY1":{ + "color":"GREEN/RED/AMBER", + "state" : "SOLID/BLINKING" + }, + "FANTRAY2":{ + "color":"GREEN/RED/AMBER", + "state" : "SOLID/BLINKING" + } + }, + + + """ + + + + load_platform_sysledutil(json_config_data) + for key in json_config_data: + for x in range(json_config_data['PLATFORM']['num_fans']): + index = x+1 + color = json_test_data[key]['SYSLED']['FANTRAY']['FANTRAY'+str(index)]['color'] + state = json_test_data[key]['SYSLED']['FANTRAY']['FANTRAY'+str(index)]['state'] + platform_sysledutil.set_status_led('fantray', index, color, state) + assert platform_sysledutil.get_status_led('fantray', index) == state,\ + "fantray"+str(index)+" sys led color is fail to changed, status = {}".format(get_status_led('fantray', index)) + +def test_for_set_psu_sysled(json_config_data, json_test_data): + """Test Purpose: Verify that the SYS PSU LED is able to set per the color and state + defined in the test config JSON + + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + SYSLED Color state setting for the FANTRAY configured in the test--config.json + + + "SYSLED": + { + "PSU":{ + "PSU1":{ + "color":"GREEN/RED/AMBER", + "state" : "SOLID/BLINKING" + }, + "PSU2":{ + "color":"GREEN/RED/AMBER", + "state" : "SOLID/BLINKING" + } + }, + + + """ + + + load_platform_sysledutil(json_config_data) + for key in json_config_data: + for x in range(json_config_data['PLATFORM']['num_psus']): + index = x+1 + color = json_test_data[key]['SYSLED']['PSU']['PSU'+str(index)]['color'] + state = json_test_data[key]['SYSLED']['PSU']['PSU'+str(index)]['state'] + platform_sysledutil.set_status_led('psu', index, color, state) + assert platform_sysledutil.get_status_led('psu', index) == state,\ + "psu"+str(index)+" sys led color is fail to changed, status = {}".format(get_status_led('psu', index)) + + +def test_for_set_sys_sysled(json_config_data, json_test_data): + """Test Purpose: Verify that the SYS LED is able to set per the color and stated + defined in the test config JSON + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + SYSLED Color state setting configured in the test--config.json + + "SYSLED": + { + "SYS":{ + "color":"GREEN/RED/AMBER", + "state" : "SOLID/BLINKING" + }, + + + """ + load_platform_sysledutil(json_config_data) + for key in json_config_data: + color = json_test_data[key]['SYSLED']['SYS']['color'] + state = json_test_data[key]['SYSLED']['SYS']['state'] + index = 0 + platform_sysledutil.set_status_led('sys', index, color, state) + + assert platform_sysledutil.get_status_led('sys', index) == state,\ + "fan"+str(index)+" sys led color is fail to changed, status = {}".format(get_status_led('sys', index)) + + +def test_for_set_loc_sysled(json_config_data, json_test_data): + + """Test Purpose: Verify that the SYS LOC LED is able to set per the color and state + defined in the test config JSON + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + SYS LOC LED Color state setting configured in the test--config.json + + + "SYSLED": + { + "LOC":{ + "color":"GREEN/RED/AMBER", + "state" : "SOLID/BLINKING" + } + + + """ + + load_platform_sysledutil(json_config_data) + for key in json_config_data: + color = json_test_data[key]['SYSLED']['LOC']['color'] + state = json_test_data[key]['SYSLED']['LOC']['state'] + index = 0 + platform_sysledutil.set_status_led('loc', index, color, state) + + assert platform_sysledutil.get_status_led('loc', index) == state,\ + "fan"+str(index)+" sys led color is fail to changed, status = {}".format(get_status_led('sys', index)) + + + diff --git a/sonic-pde-tests/sonic_pde_tests/test_os.py b/sonic-pde-tests/sonic_pde_tests/test_os.py new file mode 100644 index 0000000..bc52b9e --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/test_os.py @@ -0,0 +1,192 @@ +#!/usr/bin/python + +try: + import pytest + import json + import time + import os + import sys + import subprocess +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# Global platform specific service port +service_port = None + +# Init platform specific service port +def init_service_port(json_config_data): + global service_port + + if service_port is not None: + return service_port + + service_port = json_config_data["PLATFORM"].get("serviceport") + if service_port is None: + service_port = "eth0" + + return service_port + +def test_for_service_port_presence(json_config_data): + """Test Purpose: Verify that if the service port is present on the DUT + + Args: + arg1 (json): platform--config.json + + Example: + For a system that physically supports 1 service port + + platform--config.json + { + "PLATFORM": { + "num_serviceports": 1, + "serviceport": "eth0" + } + } + """ + init_service_port(json_config_data) + path = "/sys/class/net/" + service_port + assert os.path.isdir(path), service_port + ": no such device" + return + +def test_for_service_port_dhcp(json_config_data): + """Test Purpose: Verify that if the service port is able to obtain IP address via DHCP + + Args: + arg1 (json): platform--config.json + + Example: + For a system that physically supports 1 service port + + platform--config.json + { + "PLATFORM": { + "num_serviceports": 1, + "serviceport": "eth0" + } + } + """ + init_service_port(json_config_data) + # This is for test only, the IP of the interafce will not be changed + # As the udhcpc script is not available in PDE docker, and it's intentional + cmd = "busybox udhcpc -i " + service_port + ret = subprocess.call(cmd + " > /dev/null 2>&1", shell=True) + assert ret == 0, service_port + ": Unable to acquire DHCP address" + return + +def test_for_flooding_dmesg(json_test_data): + """Test Purpose: Verify that if the flooding dmesg message detected + + Args: + arg1 (json): test--config.json + + Example: + To scan for the flooding dmesg message by keywords: error, i2c, usb, pci + + test--config.json + { + "PLATFORM": { + "OS": + { + "flooding": { + "dmesg": [ + "error", + "i2c", + "usb", + "pci" + ] + } + } + } + } + """ + cp1 = [] + cp2 = [] + pat = json_test_data["PLATFORM"]["OS"]["flooding"]["dmesg"] + # sampling pattern counts - start point + for idx in range(len(pat)): + cmd = "dmesg | grep -c -i " + pat[idx] + pin = subprocess.Popen(cmd, + shell=True, + close_fds=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + cnt = pin.communicate()[0] + cp1.append(int(cnt)) + + # sampling period + time.sleep(3) + + # sampling pattern counts - end point + for idx in range(len(pat)): + cmd = "dmesg | grep -c -i " + pat[idx] + pin = subprocess.Popen(cmd, + shell=True, + close_fds=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + cnt = pin.communicate()[0] + cp2.append(int(cnt)) + + for idx in range(len(pat)): + assert cp2[idx] == cp1[idx], "flooding dmesg [" + pat[idx] + "] detected" + + return + +def test_for_flooding_syslog(json_test_data): + """Test Purpose: Verify that if the flooding syslog message detected + + Args: + arg1 (json): test--config.json + + Example: + To scan for the flooding syslog message by keywords: error, i2c, usb, pci + + test--config.json + { + "PLATFORM": { + "OS": + { + "flooding": { + "syslog": [ + "error", + "i2c", + "usb", + "pci" + ] + } + } + } + } + """ + cp1 = [] + cp2 = [] + pat = json_test_data["PLATFORM"]["OS"]["flooding"]["syslog"] + # sampling pattern counts - start point + for idx in range(len(pat)): + cmd = "cat /var/log/syslog | grep -c -i " + pat[idx] + pin = subprocess.Popen(cmd, + shell=True, + close_fds=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + cnt = pin.communicate()[0] + cp1.append(int(cnt)) + + # sampling period + time.sleep(3) + + # sampling pattern counts - end point + for idx in range(len(pat)): + cmd = "cat /var/log/syslog | grep -c -i " + pat[idx] + pin = subprocess.Popen(cmd, + shell=True, + close_fds=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + cnt = pin.communicate()[0] + cp2.append(int(cnt)) + + for idx in range(len(pat)): + assert cp2[idx] == cp1[idx], "flooding syslog [" + pat[idx] + "] detected" + + return diff --git a/sonic-pde-tests/sonic_pde_tests/test_platform.py b/sonic-pde-tests/sonic_pde_tests/test_platform.py new file mode 100644 index 0000000..ce613df --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/test_platform.py @@ -0,0 +1,578 @@ +try: + import pytest + import json + import time + import os + import imp + import sys + import subprocess +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +# Get Proc module info +PLATFORM_PATH = "/proc/modules" + + +def get_proc_module_info(): + file = open(PLATFORM_PATH, "r") + str = file.read() + file.close() + return str + +def getMacAddress(ifname): + ETHERNET_PATH = "/sys/class/net/"+ifname+"/address" + file = open(ETHERNET_PATH, "r") + macaddr= file.read().strip() + file.close + return macaddr + +def driver_unload(driver_name): + cmd = "rmmod "+ driver_name + os.system(cmd) + +def driver_load(driver_name): + cmd = "modprobe "+ driver_name + os.system(cmd) + + +def test_for_cpld_driver_loading(json_config_data): + + """Test Purpose: Verify that the cpld driver defined in platform config JSON + is successfully loaded in PDE + + Args: + arg1 (json): platform--config.json + + Example: + + "drivers": { + "CPLD": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "xxxx" + } + }, + } + + """ + + if json_config_data['PLATFORM']['drivers']['CPLD']['driver_info']['support'] == "false": + pytest.skip("Skip the testing due to the driver not supported") + + module_info = get_proc_module_info() + cpld_driver_name = json_config_data['PLATFORM']['drivers']['CPLD']['driver_info']['name'] + + assert module_info.find(cpld_driver_name) >= 0, \ + "Find {} driver is not loading".format(cpld_driver_name) + +def test_for_psu_driver_loading(json_config_data): + + """Test Purpose: Verify that the PSU driver defined in platform config JSON + is successfully loaded in PDE + + Args: + arg1 (json): platform--config.json + + Example: + + "drivers": { + "PSU": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "xxxx" + } + }, + } + + """ + + if json_config_data['PLATFORM']['drivers']['PSU']['driver_info']['support'] == "false": + pytest.skip("Skip the testing due to the driver not supported") + + module_info = get_proc_module_info() + psu_driver_name = json_config_data['PLATFORM']['drivers']['PSU']['driver_info']['name'] + + assert module_info.find(psu_driver_name) >= 0, \ + "Find {} driver is not loading successfully".format(psu_driver_name) + +def test_for_psu_driver_unloading(json_config_data): + + """Test Purpose: Verify that the PSU driver defined in platform config JSON + is successfully UNloaded in PDE + + Args: + arg1 (json): platform--config.json + + Example: + + "drivers": { + "PSU": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "xxxx" + } + }, + } + + """ + + if json_config_data['PLATFORM']['drivers']['PSU']['driver_info']['support'] == "false": + pytest.skip("Skip the testing due to the driver not supported") + + psu_driver_name = json_config_data['PLATFORM']['drivers']['PSU']['driver_info']['name'] + if get_proc_module_info().find(psu_driver_name) < 0: + pytest.skip("Skip the testing due to the driver not loading") + + driver_unload(psu_driver_name) + module_info = get_proc_module_info() + + if module_info.find(psu_driver_name) < 0: + driver_load(psu_driver_name) + + assert module_info.find(psu_driver_name) < 0, \ + "Find {} driver is not unloading successfully".format(psu_driver_name) + + +def test_for_fan_driver_loading(json_config_data): + + """Test Purpose: Verify that the FAN driver defined in platform config JSON + is successfully loaded in PDE + + Args: + arg1 (json): platform--config.json + + Example: + + "drivers": { + "FAN": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "xxxx" + } + }, + } + + """ + + if json_config_data['PLATFORM']['drivers']['FAN']['driver_info']['support'] == "false": + pytest.skip("Skip the testing due to the driver not supported") + + module_info = get_proc_module_info() + fan_driver_name = json_config_data['PLATFORM']['drivers']['FAN']['driver_info']['name'] + + assert module_info.find(fan_driver_name) >= 0, \ + "Find {} driver is not loading".format(fan_driver_name) + +def test_for_fan_driver_unloading(json_config_data): + + """Test Purpose: Verify that the FAN driver defined in platform config JSON + is successfully unloaded in PDE + + Args: + arg1 (json): platform--config.json + + Example: + + "drivers": { + "FAN": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "xxxx" + } + }, + } + + """ + + if json_config_data['PLATFORM']['drivers']['FAN']['driver_info']['support'] == "false": + pytest.skip("Skip the testing due to the driver not supported") + + fan_driver_name = json_config_data['PLATFORM']['drivers']['FAN']['driver_info']['name'] + if get_proc_module_info().find(fan_driver_name) < 0: + pytest.skip("Skip the testing due to the driver not loading") + + driver_unload(fan_driver_name) + module_info = get_proc_module_info() + + if module_info.find(fan_driver_name) < 0: + driver_load(fan_driver_name) + + assert module_info.find(fan_driver_name) < 0, \ + "Find {} driver is not unloading successfully".format(fan_driver_name) + + +def test_for_sfp_driver_loading(json_config_data): + + """Test Purpose: Verify that the sfp driver defined in platform config JSON + is successfully loaded in PDE + + Args: + arg1 (json): platform--config.json + + Example: + + "drivers": { + "SFP": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "xxxx" + } + }, + } + + """ + + if json_config_data['PLATFORM']['drivers']['SFP']['driver_info']['support'] == "false": + pytest.skip("Skip the testing due to the driver not supported") + + module_info = get_proc_module_info() + sfp_driver_name = json_config_data['PLATFORM']['drivers']['SFP']['driver_info']['name'] + + assert module_info.find(sfp_driver_name) >= 0, \ + "Find {} driver is not loading".format(sfp_driver_name) + + +def test_for_sfp_driver_unloading(json_config_data): + + """Test Purpose: Verify that the sfp driver defined in platform config JSON + is successfully unloaded in PDE + + Args: + arg1 (json): platform--config.json + + Example: + + "drivers": { + "SFP": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "xxxx" + } + }, + } + + """ + + if json_config_data['PLATFORM']['drivers']['SFP']['driver_info']['support'] == "false": + pytest.skip("Skip the testing due to the driver not supported") + + sfp_driver_name = json_config_data['PLATFORM']['drivers']['SFP']['driver_info']['name'] + if get_proc_module_info().find(sfp_driver_name) < 0: + pytest.skip("Skip the testing due to the driver not loading") + + driver_unload(sfp_driver_name) + module_info = get_proc_module_info() + + if module_info.find(sfp_driver_name) < 0: + driver_load(sfp_driver_name) + + assert module_info.find(sfp_driver_name) < 0, \ + "Find {} driver is not unloading successfully".format(sfp_driver_name) + + + +def test_for_temp_driver_loading(json_config_data): + + """Test Purpose: Verify that the temperature sensor driver defined in platform config JSON + is successfully loaded in PDE + + Args: + arg1 (json): platform--config.json + + Example: + + "drivers": { + "TEMP": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "xxxx" + } + }, + } + + """ + + if json_config_data['PLATFORM']['drivers']['TEMP']['driver_info']['support'] == "false": + pytest.skip("Skip the testing due to the driver not supported") + + module_info = get_proc_module_info() + temp_driver_name = json_config_data['PLATFORM']['drivers']['TEMP']['driver_info']['name'] + + assert module_info.find(temp_driver_name) >= 0, \ + "Find {} driver is not loading".format(temp_driver_name) + + +def test_for_temp_driver_unloading(json_config_data): + + """Test Purpose: Verify that the temperature driver defined in platform config JSON + is successfully unloaded in PDE + + Args: + arg1 (json): platform--config.json + + Example: + + "drivers": { + "TEMP": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "xxxx" + } + }, + } + + """ + + if json_config_data['PLATFORM']['drivers']['TEMP']['driver_info']['support'] == "false": + pytest.skip("Skip the testing due to the driver not supported") + + temp_driver_name = json_config_data['PLATFORM']['drivers']['TEMP']['driver_info']['name'] + if get_proc_module_info().find(temp_driver_name) < 0: + pytest.skip("Skip the testing due to the driver not loading") + + driver_unload(temp_driver_name) + module_info = get_proc_module_info() + + if module_info.find(temp_driver_name) < 0: + driver_load(temp_driver_name) + + assert module_info.find(temp_driver_name) < 0, \ + "Find {} driver is not unloading successfully".format(temp_driver_name) + + + +def test_for_led_driver_loading(json_config_data): + + """Test Purpose: Verify that the SYSLED driver defined in platform config JSON + is successfully loaded in PDE + + Args: + arg1 (json): platform--config.json + + Example: + + "drivers": { + "SYSLED": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "xxxx" + } + }, + } + + """ + + if json_config_data['PLATFORM']['drivers']['SYSLED']['driver_info']['support'] == "false": + pytest.skip("Skip the testing due to the driver not supported") + + module_info = get_proc_module_info() + led_driver_name = json_config_data['PLATFORM']['drivers']['SYSLED']['driver_info']['name'] + + assert module_info.find(led_driver_name) >= 0, \ + "Find {} driver is not loading".format(led_driver_name) + + + +def test_for_led_driver_unloading(json_config_data): + + """Test Purpose: Verify that the SYSLED driver defined in platform config JSON + is successfully loaded in PDE + + Args: + arg1 (json): platform--config.json + + Example: + + "drivers": { + "SYSLED": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "xxxx" + } + }, + } + + """ + + if json_config_data['PLATFORM']['drivers']['SYSLED']['driver_info']['support'] == "false": + pytest.skip("Skip the testing due to the driver not supported") + + led_driver_name = json_config_data['PLATFORM']['drivers']['SYSLED']['driver_info']['name'] + if get_proc_module_info().find(led_driver_name) < 0: + pytest.skip("Skip the testing due to the driver not loading") + + driver_unload(led_driver_name) + module_info = get_proc_module_info() + + if module_info.find(led_driver_name) < 0: + driver_load(led_driver_name) + + assert module_info.find(led_driver_name) < 0, \ + "Find {} driver is not unloading successfully".format(led_driver_name) + + + +def test_for_eeprom_driver_loading(json_config_data): + + """Test Purpose: Verify that the EEPROM driver defined in platform config JSON + is successfully loaded in PDE + + Args: + arg1 (json): platform--config.json + + Example: + + "drivers": { + "EEPROM": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "xxxx" + } + }, + } + + """ + + if json_config_data['PLATFORM']['drivers']['EEPROM']['driver_info']['support'] == "false": + pytest.skip("Skip the testing due to the driver not supported") + + module_info = get_proc_module_info() + eeprom_driver_name = json_config_data['PLATFORM']['drivers']['EEPROM']['driver_info']['name'] + + assert module_info.find(eeprom_driver_name) >= 0, \ + "Find {} driver is not loading".format(eeprom_driver_name) + + +def test_for_eeprom_driver_unloading(json_config_data): + + """Test Purpose: Verify that the EEPROM driver defined in platform config JSON + is successfully unloaded in PDE + + Args: + arg1 (json): platform--config.json + + Example: + + "drivers": { + "EEPROM": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "xxxx" + } + }, + } + + """ + + if json_config_data['PLATFORM']['drivers']['EEPROM']['driver_info']['support'] == "false": + pytest.skip("Skip the testing due to the driver not supported") + + eeprom_driver_name = json_config_data['PLATFORM']['drivers']['EEPROM']['driver_info']['name'] + if get_proc_module_info().find(eeprom_driver_name) < 0: + pytest.skip("Skip the testing due to the driver not loading") + + driver_unload(eeprom_driver_name) + module_info = get_proc_module_info() + + if module_info.find(eeprom_driver_name) < 0: + driver_load(eeprom_driver_name) + + assert module_info.find(eeprom_driver_name) < 0, \ + "Find {} driver is not unloading successfully".format(eeprom_driver_name) + + + +def test_for_mac_driver_loading(json_config_data): + + """Test Purpose: Verify that the MAC driver defined in platform config JSON + is successfully loaded in PDE + + Args: + arg1 (json): platform--config.json + + Example: + + "drivers": { + "MAC": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "xxxx" + } + }, + } + + """ + + if json_config_data['PLATFORM']['drivers']['MAC']['driver_info']['support'] == "false": + pytest.skip("Skip the testing due to the driver not supported") + + module_info = get_proc_module_info() + mac_driver_name = json_config_data['PLATFORM']['drivers']['MAC']['driver_info']['name'] + + assert module_info.find(mac_driver_name) >= 0, \ + "Find {} driver is not loading".format(mac_driver_name) + +def test_for_mac_driver_unloading(json_config_data): + + """Test Purpose: Verify that the MAC driver defined in platform config JSON + is successfully unloaded in PDE + + Args: + arg1 (json): platform--config.json + + Example: + + "drivers": { + "MAC": { + "driver_info": { + "support": "true", + "type": "ODM", + "name": "xxxx" + } + }, + } + + """ + + if json_config_data['PLATFORM']['drivers']['MAC']['driver_info']['support'] == "false": + pytest.skip("Skip the testing due to the driver not supported") + + mac_driver_name = json_config_data['PLATFORM']['drivers']['MAC']['driver_info']['name'] + if get_proc_module_info().find(mac_driver_name) < 0: + pytest.skip("Skip the testing due to the driver not loading") + + driver_unload(mac_driver_name) + module_info = get_proc_module_info() + + if module_info.find(mac_driver_name) < 0: + driver_load(mac_driver_name) + + assert module_info.find(mac_driver_name) < 0, \ + "Find {} driver is not unloading successfully".format(mac_driver_name) + + +def test_for_ethernet_mac_address(json_config_data,json_test_data): + + for key in json_config_data: + for x in range(json_config_data[key]['num_serviceports']): + ifname = json_test_data[key]['MAC']['MAC'+str(x+1)]['ifname'] + assert getMacAddress(ifname) == json_test_data['PLATFORM']['MAC']['MAC'+str(x+1)]['macaddr'], \ + "Service MAC address {} not matching with JSON configuration".format(getMacAddress(ifname)) + + + diff --git a/sonic-pde-tests/sonic_pde_tests/test_port.py b/sonic-pde-tests/sonic_pde_tests/test_port.py new file mode 100644 index 0000000..5217f05 --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/test_port.py @@ -0,0 +1,11 @@ +import pytest +import sys +import imp + + +def test_for_port(json_config_data): + pytest.skip("Not supported") + +if __name__ == '__main__': + unittest.main() + diff --git a/sonic-pde-tests/sonic_pde_tests/test_psu.py b/sonic-pde-tests/sonic_pde_tests/test_psu.py new file mode 100644 index 0000000..1b00866 --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/test_psu.py @@ -0,0 +1,135 @@ +import pytest +import sys +import imp +import subprocess +import time + +PLATFORM_SPECIFIC_MODULE_NAME = "psuutil" +PLATFORM_SPECIFIC_CLASS_NAME = "PsuUtil" + +def test_for_num_psus(json_config_data): + """Test Purpose: Verify that the numer of PSUs reported as supported by the PSU plugin matches what the platform supports. + + Args: + arg1 (json): platform--config.json + + Example: + For a system that physically supports 2 power supplies + + platform--config.json + { + "PLATFORM": { + "num_psus": 2 + } + } + """ + module = imp.load_source("psuutil","/usr/share/sonic/platform/plugins/psuutil.py") + platform_psuutil_class = getattr(module, PLATFORM_SPECIFIC_CLASS_NAME) + platform_psuutil = platform_psuutil_class() + assert platform_psuutil.get_num_psus() == json_config_data['PLATFORM']['num_psus'],"System plugin reports that {} PSUs are supported in platform".format(platform_psuutil.get_num_psus()) + +def test_for_psu_present(json_config_data, json_test_data): + """Test Purpose: Test Purpose: Verify that the PSUs that are present report as present in the PSU plugin. + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + For a system that has 2 power supplies present + + test--config.json + { + "PLATFORM": { + "PSU": { + "present": [ + 1, + 2 + ], + } + } + } + + """ + + module = imp.load_source("psuutil","/usr/share/sonic/platform/plugins/psuutil.py") + platform_psuutil_class = getattr(module, PLATFORM_SPECIFIC_CLASS_NAME) + platform_psuutil = platform_psuutil_class() + + for key in json_config_data: + psupresentlist = json_test_data[key]['PSU']['present'] + for x in psupresentlist: + assert platform_psuutil.get_psu_presence(x-1) == True, "System plugin reported PSU {} was not present".format(x) + +def test_for_psu_notpresent(json_config_data, json_test_data): + """Test Purpose: Verify that the PSUs that are not present report as not present in the PSU plugin. + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + For a system that only has power supply 2 present + + { + "PLATFORM": { + "PSU": { + "present": [ + 2 + ] + } + } + } + + """ + + module = imp.load_source("psuutil","/usr/share/sonic/platform/plugins/psuutil.py") + platform_psuutil_class = getattr(module, PLATFORM_SPECIFIC_CLASS_NAME) + platform_psuutil = platform_psuutil_class() + num_psus = platform_psuutil.get_num_psus() + for key in json_config_data: + for x in range (1, num_psus): + if platform_psuutil.get_psu_presence(x-1) == True: + Found = False; + for y in json_test_data[key]['PSU']['present']: + if x == y: + Found = True + assert (Found == True), "System plugin reported PSU {} was present".format(x) + +def test_for_psu_status(json_config_data, json_test_data): + """Test Purpose: Verify that the PSUs that are not present report proper status (True if operating properly, False if not operating properly) + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + For a system that only has power supply 2 present and both are operating properly + + test--config.json + { + "PLATFORM": { + "PSU": { + "present": [ + 1, + 2 + ], + "status": [ + "True", + "True" + ] + } + } + + """ + + module = imp.load_source("psuutil","/usr/share/sonic/platform/plugins/psuutil.py") + platform_psuutil_class = getattr(module, PLATFORM_SPECIFIC_CLASS_NAME) + platform_psuutil = platform_psuutil_class() + + for key in json_config_data: + psupresentlist = json_test_data[key]['PSU']['present'] + for x in psupresentlist: + assert platform_psuutil.get_psu_status(x-1) != json_test_data[key]['PSU']['status'], "System plugin reported PSU {} state did not match test state {}".format(x, json_test_data[key]['PSU']['status']) + + diff --git a/sonic-pde-tests/sonic_pde_tests/test_rtc.py b/sonic-pde-tests/sonic_pde_tests/test_rtc.py new file mode 100644 index 0000000..1a792ea --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/test_rtc.py @@ -0,0 +1,30 @@ +#!/usr/bin/python + +try: + import pytest + import sys + import subprocess +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# Test for RTC read +def test_for_rtc_read(): + """Test Purpose: Verify that if the RTC is readable on the DUT + + Args: + None + """ + rc = subprocess.call("hwclock > /dev/null 2>&1", shell=True) + assert rc == 0, "RTC read failed" + return + +# Test for RTC write +def test_for_rtc_write(): + """Test Purpose: Verify that if the RTC is writable on the DUT + + Args: + None + """ + rc = subprocess.call("hwclock -w > /dev/null 2>&1", shell=True) + assert rc == 0, "RTC write failed" + return diff --git a/sonic-pde-tests/sonic_pde_tests/test_sfp.py b/sonic-pde-tests/sonic_pde_tests/test_sfp.py new file mode 100644 index 0000000..66d6483 --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/test_sfp.py @@ -0,0 +1,271 @@ +#!/usr/bin/env python + +try: + import pytest + import os + import sys + import subprocess + import imp + import json + from natsort import natsorted +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +PLATFORM_PATH = "/usr/share/sonic/platform" +PLATFORM_SPECIFIC_MODULE_NAME = "sfputil" +PLATFORM_SPECIFIC_CLASS_NAME = "SfpUtil" + +# Global platform-specific sfputil class instance +platform_sfputil = None + +# Global port dictionaries +port_dict = None + +# Loads platform specific sfputil module from source +def load_platform_sfputil(): + global platform_sfputil + + if platform_sfputil is not None: + return + + try: + module_file = "/".join([PLATFORM_PATH, "plugins", PLATFORM_SPECIFIC_MODULE_NAME + ".py"]) + module = imp.load_source(PLATFORM_SPECIFIC_MODULE_NAME, module_file) + except IOError, e: + print("Failed to load platform module '%s': %s" % (PLATFORM_SPECIFIC_MODULE_NAME, str(e)), True) + + assert module is not None + + try: + platform_sfputil_class = getattr(module, PLATFORM_SPECIFIC_CLASS_NAME) + platform_sfputil = platform_sfputil_class() + except AttributeError, e: + print("Failed to instantiate '%s' class: %s" % (PLATFORM_SPECIFIC_CLASS_NAME, str(e)), True) + + assert platform_sfputil is not None + return + +# Get platform specific HwSKU path +def get_hwsku_path(): + file = open(PLATFORM_PATH + "/default_sku", "r") + line = file.readline() + list = line.split() + file.close() + return PLATFORM_PATH + "/" + list[0] + +# Loads platform port dictionaries +def load_platform_portdict(): + global port_dict + + if port_dict is not None: + return + + port_dict = {} + idx = 0 + file = open(get_hwsku_path() + "/port_config.ini", "r") + line = file.readline() + while line is not None and len(line) > 0: + line = line.strip() + if line.startswith("#"): + line = file.readline() + continue + list = line.split() + if len(list) >= 4: + idx = int(list[3]) + port_dict[list[0]] = { "index": str(idx) } + idx += 1 + line = file.readline() + + return port_dict + +# Test for SFP port number +def test_for_sfp_number(json_config_data): + """Test Purpose: Verify that the numer of SFPs reported as supported by the SFP plugin matches what the platform supports. + + Args: + arg1 (json): platform--config.json + + Example: + For a system that physically supports 32 (Q)SFP transceivers + + platform--config.json + { + "PLATFORM": { + "num_sfps": 32 + } + } + """ + load_platform_sfputil() + load_platform_portdict() + num = 0 + for intf in natsorted(port_dict.keys()): + port = int(port_dict[intf]['index']) + if not platform_sfputil._is_valid_port(port): + continue + num += 1 + + for plat in json_config_data: + assert num == int(json_config_data[plat]["num_sfps"]) + + return + +# Test for SFP presence +def test_for_sfp_present(json_config_data, json_test_data): + """Test Purpose: Verify that the presence of SFPs reported by the SFP plugin matches the physical states of the DUT. + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + For a system with 4 (Q)SFP transceivers attached on index 13,17,52,68 + + platform--config.json + { + "PLATFORM": { + "num_sfps": 32 + } + } + + test--config.json + { + "PLATFORM": { + "present": [ + 13, + 17, + 52, + 68 + ] + } + } + """ + load_platform_sfputil() + load_platform_portdict() + for intf in natsorted(port_dict.keys()): + port = int(port_dict[intf]['index']) + if not platform_sfputil._is_valid_port(port): + continue + bool = platform_sfputil.get_presence(port) + for plat in json_config_data: + list = json_test_data[plat]['SFP']['present'] + if port in list: + assert bool == True, "SFP{} is not present unexpectedly".format(port) + else: + assert bool == False, "SFP{} is present unexpectedly".format(port) + return + +# Test for SFP EEPROM +def test_for_sfp_eeprom(json_config_data, json_test_data): + """Test Purpose: Verify that the content of SFP EEPROMs pass the check code test. + + Args: + arg1 (json): platform--config.json + arg2 (json): test--config.json + + Example: + For a system with 4 (Q)SFP transceivers attached on index 13,17,52,68 + + platform--config.json + { + "PLATFORM": { + "num_sfps": 32 + } + } + + test--config.json + { + "PLATFORM": { + "present": [ + 13, + 17, + 52, + 68 + ] + } + } + """ + load_platform_sfputil() + load_platform_portdict() + for intf in natsorted(port_dict.keys()): + port = int(port_dict[intf]['index']) + if not platform_sfputil._is_valid_port(port): + continue + bool = platform_sfputil.get_presence(port) + for plat in json_config_data: + list = json_test_data[plat]['SFP']['present'] + if port in list: + assert bool == True, "SFP{} is not present unexpectedly".format(port) + code = 0 + data = platform_sfputil.get_eeprom_raw(port) + assert data != None, "SFP{}: unable to read EEPROM".format(port) + if port in platform_sfputil.osfp_ports: + #OSFP/QSFP-DD + for i in range(128, 222): + code += int(data[i], 16) + assert (code & 0xff) == int(data[222], 16), "check code error" + elif port in platform_sfputil.qsfp_ports: + #QSFP + for i in range(128, 191): + code += int(data[i], 16) + assert (code & 0xff) == int(data[191], 16), "check code error" + else: + #SFP/SFP+ + for i in range(0, 63): + code += int(data[i], 16) + assert (code & 0xff) == int(data[63], 16), "check code error" + else: + assert bool == False, "SFP{} is present".format(port) + return + +# Test for SFP LPMODE +def test_for_sfp_lpmode(): + """Test Purpose: Verify that the LPMODE of QSFP is manipulatable via SFP plugin + + Args: + None + """ + load_platform_sfputil() + load_platform_portdict() + for intf in natsorted(port_dict.keys()): + port = int(port_dict[intf]['index']) + if not platform_sfputil._is_valid_port(port): + continue + if port not in platform_sfputil.qsfp_ports: + continue + try: + bool = platform_sfputil.get_low_power_mode(port) + except NotImplementedError: + assert False, (intf + ': get_low_power_mode() is not implemented') + if bool: + try: + platform_sfputil.set_low_power_mode(port, False) + except NotImplementedError: + assert False, (intf + ': low power detected while ' + + 'set_low_power_mode() is not implemented,' + + 'link errors are expected on high power modules') + return + +# Test for SFP LPMODE +def test_for_sfp_reset(): + """Test Purpose: Verify that the RESET of QSFP is manipulatable via SFP plugin + + Args: + None + """ + load_platform_sfputil() + load_platform_portdict() + for intf in natsorted(port_dict.keys()): + port = int(port_dict[intf]['index']) + if not platform_sfputil._is_valid_port(port): + continue + if port not in platform_sfputil.qsfp_ports: + continue + try: + bool = platform_sfputil.reset(port) + assert bool, "reset failed" + except NotImplementedError: + # By defalt, it does no harm to have this unimplemented + # This failure will only be observed when users try to manually + # reset the module via CLI + pytest.skip(intf + ": reset() is not implemented") + return diff --git a/sonic-pde-tests/sonic_pde_tests/test_thermal.py b/sonic-pde-tests/sonic_pde_tests/test_thermal.py new file mode 100644 index 0000000..fcce161 --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/test_thermal.py @@ -0,0 +1,92 @@ +import pytest +import sys +import imp +import subprocess +import time + + +# Global platform-specific thermalutil class instance +platform_temputil = None + +# Loads platform specific thermalutil module from source +def load_platform_temputil(json_config_data): + global platform_temputil + + if platform_temputil is not None: + return + + try: + if json_config_data['PLATFORM']['modules']['TEMP']['support'] == "false": + pytest.skip("Skip the testing due to the python module is not supported") + + modules_dir = json_config_data['PLATFORM']['modules']['TEMP']['path'] + modules_name = json_config_data['PLATFORM']['modules']['TEMP']['name'] + class_name = json_config_data['PLATFORM']['modules']['TEMP']['class'] + modules_temp = "/usr/share/sonic/classes/" + modules_dir + "/" + modules_name + '.py' + platform_temputil_module = imp.load_source(modules_name, modules_temp) + platform_temputil_class = getattr(platform_temputil_module, class_name) + platform_temputil = platform_temputil_class() + + except AttributeError, e: + print("Failed to instantiate '%s' class: %s" % (platform_temputil_class, str(e)), True) + + return + + +def test_for_num_temp(json_config_data): + """Test Purpose: Verify that the numer of Temp sensors reported as supported + by the Termal plugin matches what the platform supports + + Args: + arg1 (json): platform--config.json + + Example: + For a system that physically supports 4 TEMPs + + platform--config.json + { + "PLATFORM": { + "num_temps": 4 + } + } + """ + + load_platform_temputil(json_config_data) + + assert platform_temputil.get_num_thermals() == json_config_data['PLATFORM']['num_temps'],\ + "verify TEMP numbers = {} not matching with platform JSON".format(platform_temputil.get_num_thermals()) + + + +def test_for_temp_read(json_config_data): + """Test Purpose: Verify that each of the Temp sensors defined in the platform config + josn is able to read + + + Args: + arg1 (json): platform--config.json + + Example: + For a system that physically supports 4 TEMPs + + platform--config.json + { + "PLATFORM": { + num_temps": 4 + } + } + """ + + + load_platform_temputil(json_config_data) + + for x in range(json_config_data['PLATFORM']['num_temps']): + assert platform_temputil._get_thermal_node_val(x+1) != None, \ + "verify TEMP"+str(x+1)+" read is False".format(platform_temputil._get_thermal_node_val(x+1)) + + +if __name__ == '__main__': + unittest.main() + + + diff --git a/sonic-pde-tests/sonic_pde_tests/test_usb.py b/sonic-pde-tests/sonic_pde_tests/test_usb.py new file mode 100644 index 0000000..a823c5a --- /dev/null +++ b/sonic-pde-tests/sonic_pde_tests/test_usb.py @@ -0,0 +1,153 @@ +#!/usr/bin/python + +try: + import os + import sys + import json + import time + import pytest + import subprocess +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# Test for USB storage support +def test_for_usb_storage(): + """Test Purpose: Verify that if the USB storage device support is enable in the kernel + + Args: + None + """ + cmd = "cat /boot/config-* | grep ^CONFIG_USB_STORAGE=" + ret = subprocess.call(cmd + " > /dev/null 2>&1", shell=True) + assert ret == 0, "USB storage support is disabled in the kernel" + return + +# Test for FAT filesystem support +def test_for_usb_fat(): + """Test Purpose: Verify that if the MSDOS/VFAT/FAT filesystem support is enable in the kernel + + Args: + None + """ + cmd = "cat /boot/config-* | grep ^CONFIG_FAT_FS=" + ret = subprocess.call(cmd + " > /dev/null 2>&1", shell=True) + assert ret == 0, "FAT support is disabled in the kernel" + cmd = "cat /boot/config-* | grep ^CONFIG_VFAT_FS=" + ret = subprocess.call(cmd + " > /dev/null 2>&1", shell=True) + assert ret == 0, "VFAT support is disabled in the kernel" + cmd = "cat /boot/config-* | grep ^CONFIG_MSDOS_FS=" + ret = subprocess.call(cmd + " > /dev/null 2>&1", shell=True) + assert ret == 0, "MSDOS support is disabled in the kernel" + return + +# Test for NTFS filesystem support +def test_for_usb_ntfs(): + """Test Purpose: Verify that if the NTFS filesystem support is enable in the kernel + + Args: + None + """ + cmd = "cat /boot/config-* | grep ^CONFIG_NTFS_FS=" + ret = subprocess.call(cmd + " > /dev/null 2>&1", shell=True) + assert ret == 0, "NTFS support is disabled in the kernel" + return + +# Test for EXT4 filesystem support +def test_for_usb_ext4(): + """Test Purpose: Verify that if the EXT4 filesystem support is enable in the kernel + + Args: + None + """ + cmd = "cat /boot/config-* | grep ^CONFIG_EXT4_FS=" + ret = subprocess.call(cmd + " > /dev/null 2>&1", shell=True) + assert ret == 0, "EXT4 support is disabled in the kernel" + return + +# Test for the presence of external USB storage +def test_for_usb_presence(json_test_data): + """Test Purpose: Verify that the attached USB storage is detected on the DUT + + Args: + arg1 (json): test--config.json + + Example: + To enable the external USB storage test + + test--config.json + { + "PLATFORM": { + "USB": { + "enable": "yes", + "device": "sdb", + "mountpoint": "/media/usb-storage" + }, + } + } + """ + doit = json_test_data["PLATFORM"]["USB"]["enable"] + if doit is None or "yes" != doit: + pytest.skip("USB disabled") + return + + node = json_test_data["PLATFORM"]["USB"]["device"] + assert node is not None and node.startswith("sd"), "invalid device node" + + path = "/sys/class/block/" + node + assert os.path.isdir(path), node + ": no such device" + +# Test for mounting external USB storage (i.e. filesystem read) +def test_for_usb_mount(json_test_data): + """Test Purpose: Verify that the attached USB storage is able to be mounted on the DUT + + Args: + arg1 (json): test--config.json + + Example: + To enable the external USB storage test + + test--config.json + { + "PLATFORM": { + "USB": { + "enable": "yes", + "device": "sdb", + "mountpoint": "/media/usb-storage" + }, + } + } + """ + doit = json_test_data["PLATFORM"]["USB"]["enable"] + if doit is None or "yes" != doit: + pytest.skip("USB disabled") + return + + device = json_test_data["PLATFORM"]["USB"]["device"] + assert device is not None and device.startswith("sd"), "invalid device node" + + mountpoint = json_test_data["PLATFORM"]["USB"]["mountpoint"] + assert mountpoint is not None and mountpoint.startswith("/media"), "invalid mount point" + + # umount the usb if it's still there + rc = subprocess.call("mount | grep " + mountpoint + " > /dev/null 2>&1", shell=True) + if rc == 0: + rc = subprocess.call("umount " + mountpoint + " > /dev/null 2>&1", shell=True) + time.sleep(3) + + # create mount point + rc = subprocess.call("mkdir -p " + mountpoint + " > /dev/null 2>&1", shell=True) + assert rc == 0, "Unable to create mount point" + + # mount the USB (try to mount partition 1 and then partition 0) + if os.path.isdir("/sys/class/block/" + device + "1"): + cmd = "mount /dev/" + device + "1 " + mountpoint + " > /dev/null 2>&1" + elif os.path.isdir("/sys/class/block/" + device): + cmd = "mount /dev/" + device + " " + mountpoint + " > /dev/null 2>&1" + else: + cmd = "false" + rc = subprocess.call(cmd, shell=True) + assert rc == 0, "Unable to mount the external USB" + + # umount the USB + rc = subprocess.call("umount " + mountpoint + " > /dev/null 2>&1", shell=True) + return diff --git a/sonic-pde-tests/stdeb.cfg b/sonic-pde-tests/stdeb.cfg new file mode 100644 index 0000000..db4574b --- /dev/null +++ b/sonic-pde-tests/stdeb.cfg @@ -0,0 +1 @@ +[DEFAULT]