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]