From 5102d3e5691dd36fd72c2678e6604a4535190500 Mon Sep 17 00:00:00 2001
From: Syd Logan
Date: Mon, 15 Jun 2020 12:58:54 -0700
Subject: [PATCH 1/9] swss: Add support to swss for gearbox phys
* builds on support for multiple switches in sonic-sairedis
* adds gearsync daemon
* parsers for gearbox-related configuration files, plus unit tests
* gearboxutils for determining if gearbox supported and other functions
* changes to portsorch and orchagent to support gearbox creation and attributes
HLD is located at https://github.com/Azure/SONiC/blob/b817a12fd89520d3fd26bbc5897487928e7f6de7/doc/gearbox/gearbox_mgr_design.md
Signed-off-by: syd.logan@broadcom.com
---
Makefile.am | 3 +-
cfgmgr/Makefile.am | 2 +-
configure.ac | 2 +
gearsyncd/Makefile.am | 15 +
gearsyncd/gearboxparser.cpp | 248 ++
gearsyncd/gearboxparser.h | 29 +
gearsyncd/gearparserbase.cpp | 67 +
gearsyncd/gearparserbase.h | 62 +
gearsyncd/gearsyncd.cpp | 164 +
gearsyncd/phyparser.cpp | 398 +++
gearsyncd/phyparser.h | 32 +
gearsyncd/tests/Makefile.am | 21 +
...rbox_config_empty_ethernet_line_lanes.json | 49 +
...ox_config_empty_ethernet_system_lanes.json | 49 +
.../gearbox_config_invalid_array.json | 49 +
.../negative/gearbox_config_invalid_json.json | 49 +
...earbox_config_invalid_phy_config_file.json | 49 +
...gearbox_config_missing_ethernet_index.json | 47 +
...nfig_missing_ethernet_line_lane_speed.json | 49 +
...ox_config_missing_ethernet_line_lanes.json | 48 +
...earbox_config_missing_ethernet_phy_id.json | 48 +
...ig_missing_ethernet_system_lane_speed.json | 49 +
..._config_missing_ethernet_system_lanes.json | 48 +
.../gearbox_config_missing_interfaces.json | 26 +
.../gearbox_config_missing_phy_address.json | 44 +
.../gearbox_config_missing_phy_bus_id.json | 44 +
...earbox_config_missing_phy_config_file.json | 44 +
...rbox_config_missing_phy_firmware_path.json | 44 +
.../gearbox_config_missing_phy_id.json | 45 +
.../gearbox_config_missing_phy_lib_name.json | 44 +
.../gearbox_config_missing_phy_name.json | 44 +
...gearbox_config_missing_phy_phy_access.json | 44 +
...nfig_missing_phy_sai_init_config_file.json | 45 +
.../negative/gearbox_config_missing_phys.json | 23 +
.../negative/phy_config_invalid_array.json | 146 +
.../negative/phy_config_invalid_boolean.json | 180 +
.../negative/phy_config_invalid_boolean2.json | 181 +
.../negative/phy_config_invalid_json.json | 180 +
.../negative/phy_config_lanes_missing_id.json | 179 +
..._config_lanes_missing_line_rx_lanemap.json | 179 +
..._lanes_missing_line_to_system_lanemap.json | 179 +
..._config_lanes_missing_line_tx_lanemap.json | 179 +
...hy_config_lanes_missing_local_lane_id.json | 179 +
.../phy_config_lanes_missing_mdio_addr.json | 179 +
.../phy_config_lanes_missing_rx_polarity.json | 179 +
.../phy_config_lanes_missing_system_side.json | 179 +
.../phy_config_lanes_missing_tx_polarity.json | 179 +
.../negative/phy_config_missing_address.json | 180 +
.../negative/phy_config_missing_lanes.json | 46 +
.../negative/phy_config_missing_mode.json | 145 +
.../negative/phy_config_missing_name.json | 145 +
.../phy_config_missing_port_ref_clk.json | 145 +
.../phy_config_ports_empty_line_lanes.json | 146 +
.../phy_config_ports_empty_system_lanes.json | 146 +
.../negative/phy_config_ports_missing_id.json | 179 +
...g_ports_missing_line_adver_asym_pause.json | 179 +
...fig_ports_missing_line_adver_auto_neg.json | 179 +
...y_config_ports_missing_line_adver_fec.json | 179 +
...g_ports_missing_line_adver_media_type.json | 179 +
...config_ports_missing_line_adver_speed.json | 179 +
...hy_config_ports_missing_line_auto_neg.json | 179 +
.../phy_config_ports_missing_line_fec.json | 179 +
...y_config_ports_missing_line_intf_type.json | 179 +
..._config_ports_missing_line_lane_speed.json | 179 +
.../phy_config_ports_missing_line_lanes.json | 145 +
...hy_config_ports_missing_line_loopback.json | 179 +
..._config_ports_missing_line_media_type.json | 179 +
.../phy_config_ports_missing_line_speed.json | 179 +
...hy_config_ports_missing_line_training.json | 179 +
.../phy_config_ports_missing_mdio_addr.json | 179 +
..._config_ports_missing_system_auto_neg.json | 179 +
.../phy_config_ports_missing_system_fec.json | 179 +
...onfig_ports_missing_system_lane_speed.json | 179 +
...phy_config_ports_missing_system_lanes.json | 145 +
..._config_ports_missing_system_loopback.json | 179 +
...phy_config_ports_missing_system_speed.json | 178 +
..._config_ports_missing_system_training.json | 179 +
.../configs/positive/gearbox_config_1.json | 49 +
.../tests/configs/positive/phy1_config_1.json | 180 +
.../tests/configs/positive/phy2_config_1.json | 115 +
gearsyncd/tests/cunit/Automated.c | 623 ++++
gearsyncd/tests/cunit/Automated.cpp | 623 ++++
gearsyncd/tests/cunit/Automated.h | 90 +
gearsyncd/tests/cunit/Basic.c | 334 ++
gearsyncd/tests/cunit/Basic.cpp | 334 ++
gearsyncd/tests/cunit/Basic.h | 113 +
gearsyncd/tests/cunit/CUError.c | 231 ++
gearsyncd/tests/cunit/CUError.cpp | 231 ++
gearsyncd/tests/cunit/CUError.h | 199 ++
gearsyncd/tests/cunit/CUnit.h | 383 +++
gearsyncd/tests/cunit/CUnit_intl.h | 62 +
gearsyncd/tests/cunit/Console.c | 735 +++++
gearsyncd/tests/cunit/Console.cpp | 735 +++++
gearsyncd/tests/cunit/Console.h | 60 +
gearsyncd/tests/cunit/MyMem.c | 585 ++++
gearsyncd/tests/cunit/MyMem.cpp | 585 ++++
gearsyncd/tests/cunit/MyMem.h | 104 +
gearsyncd/tests/cunit/TestDB.c | 2773 ++++++++++++++++
gearsyncd/tests/cunit/TestDB.cpp | 2773 ++++++++++++++++
gearsyncd/tests/cunit/TestDB.h | 914 ++++++
gearsyncd/tests/cunit/TestRun.c | 2923 +++++++++++++++++
gearsyncd/tests/cunit/TestRun.cpp | 2913 ++++++++++++++++
gearsyncd/tests/cunit/TestRun.h | 444 +++
gearsyncd/tests/cunit/Util.c | 609 ++++
gearsyncd/tests/cunit/Util.cpp | 609 ++++
gearsyncd/tests/cunit/Util.h | 158 +
gearsyncd/tests/testgearparser.cpp | 150 +
gearsyncd/tests/testphyparser.cpp | 193 ++
lib/gearboxutils.cpp | 459 +++
lib/gearboxutils.h | 112 +
orchagent/Makefile.am | 3 +-
orchagent/main.cpp | 57 +-
orchagent/portsorch.cpp | 573 +++-
orchagent/portsorch.h | 36 +-
orchagent/saihelper.cpp | 113 +-
orchagent/saihelper.h | 5 +-
portsyncd/Makefile.am | 4 +-
tests/mock_tests/Makefile.am | 3 +-
118 files changed, 31432 insertions(+), 86 deletions(-)
create mode 100644 gearsyncd/Makefile.am
create mode 100644 gearsyncd/gearboxparser.cpp
create mode 100644 gearsyncd/gearboxparser.h
create mode 100644 gearsyncd/gearparserbase.cpp
create mode 100644 gearsyncd/gearparserbase.h
create mode 100644 gearsyncd/gearsyncd.cpp
create mode 100644 gearsyncd/phyparser.cpp
create mode 100644 gearsyncd/phyparser.h
create mode 100644 gearsyncd/tests/Makefile.am
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_empty_ethernet_line_lanes.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_empty_ethernet_system_lanes.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_invalid_array.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_invalid_json.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_invalid_phy_config_file.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_ethernet_index.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_ethernet_line_lane_speed.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_ethernet_line_lanes.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_ethernet_phy_id.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_ethernet_system_lane_speed.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_ethernet_system_lanes.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_interfaces.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_phy_address.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_phy_bus_id.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_phy_config_file.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_phy_firmware_path.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_phy_id.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_phy_lib_name.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_phy_name.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_phy_phy_access.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_phy_sai_init_config_file.json
create mode 100644 gearsyncd/tests/configs/negative/gearbox_config_missing_phys.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_invalid_array.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_invalid_boolean.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_invalid_boolean2.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_invalid_json.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_lanes_missing_id.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_lanes_missing_line_rx_lanemap.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_lanes_missing_line_to_system_lanemap.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_lanes_missing_line_tx_lanemap.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_lanes_missing_local_lane_id.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_lanes_missing_mdio_addr.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_lanes_missing_rx_polarity.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_lanes_missing_system_side.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_lanes_missing_tx_polarity.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_missing_address.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_missing_lanes.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_missing_mode.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_missing_name.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_missing_port_ref_clk.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_empty_line_lanes.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_empty_system_lanes.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_id.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_line_adver_asym_pause.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_line_adver_auto_neg.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_line_adver_fec.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_line_adver_media_type.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_line_adver_speed.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_line_auto_neg.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_line_fec.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_line_intf_type.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_line_lane_speed.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_line_lanes.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_line_loopback.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_line_media_type.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_line_speed.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_line_training.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_mdio_addr.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_system_auto_neg.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_system_fec.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_system_lane_speed.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_system_lanes.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_system_loopback.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_system_speed.json
create mode 100644 gearsyncd/tests/configs/negative/phy_config_ports_missing_system_training.json
create mode 100644 gearsyncd/tests/configs/positive/gearbox_config_1.json
create mode 100644 gearsyncd/tests/configs/positive/phy1_config_1.json
create mode 100644 gearsyncd/tests/configs/positive/phy2_config_1.json
create mode 100644 gearsyncd/tests/cunit/Automated.c
create mode 100644 gearsyncd/tests/cunit/Automated.cpp
create mode 100644 gearsyncd/tests/cunit/Automated.h
create mode 100644 gearsyncd/tests/cunit/Basic.c
create mode 100644 gearsyncd/tests/cunit/Basic.cpp
create mode 100644 gearsyncd/tests/cunit/Basic.h
create mode 100644 gearsyncd/tests/cunit/CUError.c
create mode 100644 gearsyncd/tests/cunit/CUError.cpp
create mode 100644 gearsyncd/tests/cunit/CUError.h
create mode 100644 gearsyncd/tests/cunit/CUnit.h
create mode 100644 gearsyncd/tests/cunit/CUnit_intl.h
create mode 100644 gearsyncd/tests/cunit/Console.c
create mode 100644 gearsyncd/tests/cunit/Console.cpp
create mode 100644 gearsyncd/tests/cunit/Console.h
create mode 100644 gearsyncd/tests/cunit/MyMem.c
create mode 100644 gearsyncd/tests/cunit/MyMem.cpp
create mode 100644 gearsyncd/tests/cunit/MyMem.h
create mode 100644 gearsyncd/tests/cunit/TestDB.c
create mode 100644 gearsyncd/tests/cunit/TestDB.cpp
create mode 100644 gearsyncd/tests/cunit/TestDB.h
create mode 100644 gearsyncd/tests/cunit/TestRun.c
create mode 100644 gearsyncd/tests/cunit/TestRun.cpp
create mode 100644 gearsyncd/tests/cunit/TestRun.h
create mode 100644 gearsyncd/tests/cunit/Util.c
create mode 100644 gearsyncd/tests/cunit/Util.cpp
create mode 100644 gearsyncd/tests/cunit/Util.h
create mode 100644 gearsyncd/tests/testgearparser.cpp
create mode 100644 gearsyncd/tests/testphyparser.cpp
create mode 100644 lib/gearboxutils.cpp
create mode 100644 lib/gearboxutils.h
diff --git a/Makefile.am b/Makefile.am
index b2e8154888..6fa155d678 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,4 @@
-
-SUBDIRS = fpmsyncd neighsyncd portsyncd mclagsyncd natsyncd orchagent swssconfig cfgmgr tests
+SUBDIRS = fpmsyncd neighsyncd portsyncd mclagsyncd natsyncd orchagent swssconfig cfgmgr tests gearsyncd gearsyncd/tests
if HAVE_LIBTEAM
SUBDIRS += teamsyncd
diff --git a/cfgmgr/Makefile.am b/cfgmgr/Makefile.am
index 7178cad1c6..001c6f1f99 100644
--- a/cfgmgr/Makefile.am
+++ b/cfgmgr/Makefile.am
@@ -1,4 +1,4 @@
-INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/orchagent -I $(top_srcdir)/warmrestart -I $(top_srcdir)/orchagent/flex_counter
+INCLUDES = -I$(top_srcdir)/lib -I $(top_srcdir) -I $(top_srcdir)/orchagent -I $(top_srcdir)/warmrestart -I $(top_srcdir)/orchagent/flex_counter
CFLAGS_SAI = -I /usr/include/sai
LIBNL_CFLAGS = -I/usr/include/libnl3
LIBNL_LIBS = -lnl-genl-3 -lnl-route-3 -lnl-3
diff --git a/configure.ac b/configure.ac
index 2d5c1fc106..81e2752457 100644
--- a/configure.ac
+++ b/configure.ac
@@ -89,6 +89,8 @@ AC_CONFIG_FILES([
orchagent/Makefile
fpmsyncd/Makefile
neighsyncd/Makefile
+ gearsyncd/Makefile
+ gearsyncd/tests/Makefile
natsyncd/Makefile
portsyncd/Makefile
teamsyncd/Makefile
diff --git a/gearsyncd/Makefile.am b/gearsyncd/Makefile.am
new file mode 100644
index 0000000000..34bffb7633
--- /dev/null
+++ b/gearsyncd/Makefile.am
@@ -0,0 +1,15 @@
+INCLUDES = -I $(top_srcdir)/lib -I $(top_srcdir) -I $(top_srcdir)/warmrestart -I $(top_srcdir)/cfgmgr
+
+bin_PROGRAMS = gearsyncd
+
+if DEBUG
+DBGFLAGS = -ggdb -DDEBUG
+else
+DBGFLAGS = -g
+endif
+
+gearsyncd_SOURCES = $(top_srcdir)/lib/gearboxutils.cpp gearsyncd.cpp gearparserbase.cpp gearboxparser.cpp phyparser.cpp $(top_srcdir)/cfgmgr/shellcmd.h
+
+gearsyncd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(COV_CFLAGS) $(ASAN_CFLAGS)
+
+gearsyncd_LDADD = -lnl-3 -lnl-route-3 -lswsscommon $(COV_LDFLAGS) $(ASAN_LDFLAGS)
diff --git a/gearsyncd/gearboxparser.cpp b/gearsyncd/gearboxparser.cpp
new file mode 100644
index 0000000000..80809fb27d
--- /dev/null
+++ b/gearsyncd/gearboxparser.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2019-2020 Broadcom Inc.
+ *
+ * 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.
+ */
+
+#include "gearboxparser.h"
+#include "phyparser.h"
+#include
+
+void
+GearboxParser::notifyGearboxConfigDone(bool success)
+{
+ swss::ProducerStateTable *p = getProducerStateTable().get();
+
+ swss::FieldValueTuple finish_notice("success", std::to_string(success));
+ std::vector attrs = { finish_notice };
+
+ p->set("GearboxConfigDone", attrs);
+}
+
+bool
+GearboxParser::parse()
+{
+ json root;
+
+ try {
+ root = getJSONRoot();
+ } catch (const std::exception& e) {
+ SWSS_LOG_ERROR("JSON root not parseable");
+ return false;
+ }
+
+ json phys, phy, interfaces, interface, val, lanes;
+
+ std::vector attrs;
+
+ try {
+ phys = root["phys"];
+ if (phys.size() == 0) {
+ SWSS_LOG_ERROR("zero-sized 'phys' field in gearbox configuration");
+ return false;
+ }
+ } catch (const std::exception& e) {
+ SWSS_LOG_ERROR("unable to read gearbox configuration (invalid format)");
+ return false;
+ }
+
+ if (true) {
+ for (uint32_t iter = 0; iter < phys.size(); iter++) {
+ phy = phys[iter];
+ try {
+ attrs.clear();
+ swss::FieldValueTuple attr;
+ if (phy.find("phy_id") == phy.end()) {
+ SWSS_LOG_ERROR("missing 'phy_id' field in 'phys' item %d in gearbox configuration", iter);
+ return false;
+ }
+ val = phy["phy_id"];
+ int phyId = val.get();
+ attr = std::make_pair("phy_id", std::to_string(phyId));
+ attrs.push_back(attr);
+ if (phy.find("name") == phy.end()) {
+ SWSS_LOG_ERROR("missing 'name' field in 'phys' item %d in gearbox configuration", iter);
+ return false;
+ }
+ val = phy["name"];
+ std::string name(val.get());
+ attr = std::make_pair("name", std::string(val.get()));
+ attrs.push_back(attr);
+ if (phy.find("address") == phy.end()) {
+ SWSS_LOG_ERROR("missing 'address' field in 'phys' item %d in gearbox configuration", iter);
+ return false;
+ }
+ val = phy["address"];
+ attr = std::make_pair("address", std::string(val.get()));
+ attrs.push_back(attr);
+ if (phy.find("lib_name") == phy.end()) {
+ SWSS_LOG_ERROR("missing 'lib_name' field in 'phys' item %d in gearbox configuration", iter);
+ return false;
+ }
+ val = phy["lib_name"];
+ attr = std::make_pair("lib_name", std::string(val.get()));
+ attrs.push_back(attr);
+ if (phy.find("firmware_path") == phy.end()) {
+ SWSS_LOG_ERROR("missing 'firmware_path' field in 'phys' item %d in gearbox configuration", iter);
+ return false;
+ }
+ val = phy["firmware_path"];
+ attr = std::make_pair("firmware_path", std::string(val.get()));
+ attrs.push_back(attr);
+ if (phy.find("config_file") == phy.end()) {
+ SWSS_LOG_ERROR("missing 'config_file' field in 'phys' item %d in gearbox configuration", iter);
+ return false;
+ }
+ val = phy["config_file"];
+ std::string cfgFile(val.get());
+ attr = std::make_pair("config_file", cfgFile);
+ attrs.push_back(attr);
+ if (phy.find("sai_init_config_file") == phy.end()) {
+ SWSS_LOG_ERROR("missing 'sai_init_config_file' field in 'phys' item %d in gearbox configuration", iter);
+ return false;
+ }
+ val = phy["sai_init_config_file"];
+ std::string bcmCfgFile(std::string(val.get()));
+ attr = std::make_pair("sai_init_config_file", bcmCfgFile);
+ attrs.push_back(attr);
+ if (phy.find("phy_access") == phy.end()) {
+ SWSS_LOG_ERROR("missing 'phy_access' field in 'phys' item %d in gearbox configuration", iter);
+ return false;
+ }
+ val = phy["phy_access"];
+ attr = std::make_pair("phy_access", std::string(val.get()));
+ attrs.push_back(attr);
+ if (phy.find("bus_id") == phy.end()) {
+ SWSS_LOG_ERROR("missing 'bus_id' field in 'phys' item %d in gearbox configuration", iter);
+ return false;
+ }
+ val = phy["bus_id"];
+ attr = std::make_pair("bus_id", std::to_string(val.get()));
+ attrs.push_back(attr);
+ std::string key;
+ key = "phy:" + std::to_string(phyId);
+ if (getWriteToDb() == true) {
+ writeToDb(key, attrs);
+ }
+ PhyParser p;
+ p.setPhyId(phyId);
+ p.setWriteToDb(getWriteToDb());
+ p.setConfigPath(cfgFile);
+ if (p.parse() == false) {
+ SWSS_LOG_ERROR("phy parser failed to parse item %d in gearbox configuration", iter);
+ return false;
+ }
+ } catch (const std::exception& e) {
+ SWSS_LOG_ERROR("unable to read 'phys' item %d in gearbox configuration (invalid format)", iter);
+ return false;
+ }
+ }
+ } else {
+ SWSS_LOG_ERROR("missing 'phys' field in gearbox configuration");
+ return false;
+ }
+
+ if (root.find("interfaces") != root.end()) {
+ interfaces = root["interfaces"]; // vec
+ if (interfaces.size() == 0) {
+ SWSS_LOG_ERROR("zero-sized 'interfaces' field in gearbox configuration");
+ return false;
+ }
+ for (uint32_t iter = 0; iter < interfaces.size(); iter++) {
+ attrs.clear();
+ interface = interfaces[iter];
+ try {
+ swss::FieldValueTuple attr;
+
+ if (interface.find("name") == interface.end()) {
+ SWSS_LOG_ERROR("missing 'name' field in 'interfaces' item %d in gearbox configuration", iter);
+ return false;
+ }
+ val = interface["name"];
+ attr = std::make_pair("name", std::string(val.get()));
+ attrs.push_back(attr);
+
+ if (interface.find("index") == interface.end()) {
+ SWSS_LOG_ERROR("missing 'index' field in 'interfaces' item %d in gearbox configuration", iter);
+ return false;
+ }
+ val = interface["index"];
+ int index = val.get();
+ attr = std::make_pair("index", std::to_string(index));
+ attrs.push_back(attr);
+
+ if (interface.find("phy_id") == interface.end()) {
+ SWSS_LOG_ERROR("missing 'phy_id' field in 'interfaces' item %d in gearbox configuration", iter);
+ return false;
+ }
+ val = interface["phy_id"];
+ attr = std::make_pair("phy_id", std::to_string(val.get()));
+ attrs.push_back(attr);
+
+ if (interface.find("system_lanes") != interface.end()) {
+ lanes = interface["system_lanes"]; // vec
+ std::string laneStr("");
+ if (lanes.size() == 0) {
+ SWSS_LOG_ERROR("zero-sized 'system_lanes' field in 'interfaces' item %d in gearbox configuration", iter);
+ return false;
+ }
+ for (uint32_t iter2 = 0; iter2 < lanes.size(); iter2++) {
+ val = lanes[iter2];
+ if (laneStr.length() > 0) {
+ laneStr += ",";
+ }
+ laneStr += std::to_string(val.get());
+ }
+ attr = std::make_pair("system_lanes", laneStr);
+ attrs.push_back(attr);
+ } else {
+ SWSS_LOG_ERROR("missing 'system_lanes' field in 'interfaces' item %d in gearbox configuration", iter);
+ return false;
+ }
+
+ if (interface.find("line_lanes") != interface.end()) {
+ lanes = interface["line_lanes"]; // vec
+ std::string laneStr("");
+ if (lanes.size() == 0) {
+ SWSS_LOG_ERROR("zero-sized 'line_lanes' field in 'interfaces' item %d in gearbox configuration", iter);
+ return false;
+ }
+ for (uint32_t iter2 = 0; iter2 < lanes.size(); iter2++) {
+ val = lanes[iter2];
+ if (laneStr.length() > 0) {
+ laneStr += ",";
+ }
+ laneStr += std::to_string(val.get());
+ }
+ attr = std::make_pair("line_lanes", laneStr);
+ attrs.push_back(attr);
+ } else {
+ SWSS_LOG_ERROR("missing 'line_lanes' field in 'interfaces' item %d in gearbox configuration", iter);
+ return false;
+ }
+ std::string key;
+ key = "interface:" + std::to_string(index);
+ if (getWriteToDb() == true) {
+ writeToDb(key, attrs);
+ }
+ } catch (const std::exception& e) {
+ SWSS_LOG_ERROR("unable to read 'interfaces' item %d in gearbox configuration (invalid format)", iter);
+ return false;
+ }
+ }
+ } else {
+ SWSS_LOG_ERROR("unable to read 'interfaces' item in gearbox configuration");
+ return false;
+ }
+ return true;
+}
diff --git a/gearsyncd/gearboxparser.h b/gearsyncd/gearboxparser.h
new file mode 100644
index 0000000000..9620d7bfeb
--- /dev/null
+++ b/gearsyncd/gearboxparser.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019 Broadcom Inc.
+ *
+ * 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.
+ */
+
+#if !defined(__GEARBOX_PARSER_H__)
+#define __GEARBOX_PARSER_H__
+
+#include "gearparserbase.h"
+
+class GearboxParser: public GearParserBase
+{
+public:
+ bool parse();
+ void notifyGearboxConfigDone(bool success);
+};
+
+#endif /* __GEARBOX_PARSER_H__ */
diff --git a/gearsyncd/gearparserbase.cpp b/gearsyncd/gearparserbase.cpp
new file mode 100644
index 0000000000..3f1c949b2f
--- /dev/null
+++ b/gearsyncd/gearparserbase.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2019 Broadcom Inc.
+ *
+ * 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.
+ */
+
+#include "gearparserbase.h"
+#include
+#include
+#include
+
+void
+GearParserBase::init() {
+ m_writeToDb = false;
+ m_rootInit = false;
+ m_applDb = std::unique_ptr{new swss::DBConnector(APPL_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0)};
+ m_producerStateTable = std::unique_ptr{new swss::ProducerStateTable(m_applDb.get(), APP_GEARBOX_TABLE_NAME)};
+}
+
+GearParserBase::GearParserBase() {
+ init();
+}
+
+GearParserBase::~GearParserBase() {
+}
+
+json &
+GearParserBase::getJSONRoot()
+{
+ // lazy instantiate
+
+ if (m_rootInit == false) {
+
+ std::ifstream infile(getConfigPath());
+ if (infile.is_open())
+ {
+ std::string jsonBuffer;
+ std::string line;
+
+ while (getline(infile, line)) {
+ jsonBuffer += line;
+ }
+ infile.close();
+
+ m_root = json::parse(jsonBuffer.c_str());
+ m_rootInit = true;
+ }
+ }
+ return m_root;
+}
+
+bool
+GearParserBase::writeToDb(std::string &key, std::vector &attrs)
+{
+ m_producerStateTable.get()->set(key.c_str(), attrs);
+ return true;
+}
diff --git a/gearsyncd/gearparserbase.h b/gearsyncd/gearparserbase.h
new file mode 100644
index 0000000000..4454c0ba83
--- /dev/null
+++ b/gearsyncd/gearparserbase.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2019 Broadcom Inc.
+ *
+ * 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.
+ */
+
+#if !defined(__GEAR_PARSER_BASE_H__)
+#define __GEAR_PARSER_BASE_H__
+
+#include "dbconnector.h"
+#include "producerstatetable.h"
+#include
+#include
+#include
+
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#include "swss/json.hpp"
+#pragma GCC diagnostic pop
+
+using json = nlohmann::json;
+
+class GearParserBase
+{
+public:
+ GearParserBase();
+ virtual ~GearParserBase();
+ virtual bool parse() = 0;
+ void setWriteToDb(bool val) {m_writeToDb = val;}
+ bool getWriteToDb() {return m_writeToDb;}
+ void setConfigPath(std::string &path) {m_cfgPath = path;}
+ const std::string getConfigPath() {return m_cfgPath;}
+ std::unique_ptr &getProducerStateTable() {return m_producerStateTable;}
+
+protected:
+ bool writeToDb(std::string &key, std::vector &attrs);
+ json &getJSONRoot();
+
+private:
+ void init();
+ std::unique_ptr m_cfgDb;
+ std::unique_ptr m_applDb;
+ std::unique_ptr m_stateDb;
+ std::unique_ptr m_producerStateTable;
+ std::string m_cfgPath;
+ bool m_writeToDb;
+ json m_root;
+ bool m_rootInit;
+};
+
+#endif // __GEAR_PARSER_BASE_H__
diff --git a/gearsyncd/gearsyncd.cpp b/gearsyncd/gearsyncd.cpp
new file mode 100644
index 0000000000..f4082bb0be
--- /dev/null
+++ b/gearsyncd/gearsyncd.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2019 Broadcom Inc.
+ *
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
.
+ *
+ * @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/gearsyncd/tests/cunit/TestRun.c b/gearsyncd/tests/cunit/TestRun.c
new file mode 100644
index 0000000000..efd88e48fc
--- /dev/null
+++ b/gearsyncd/tests/cunit/TestRun.c
@@ -0,0 +1,2923 @@
+/*
+ * 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
+#if NOT_YET
+#include
+#else
+#include
+#endif
+#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;
+#if NOT_YET
+ pthread_t tid;
+#endif
+ 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 NOT_YET
+ 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);
+ }
+ }
+#endif
+ (*pTest->pTestFunc)();
+#if NOT_YET
+ if (collect_syslog){
+ sleep(1);
+ pthread_cancel(tid);
+ }
+#endif
+ }
+ }
+
+ 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/gearsyncd/tests/cunit/TestRun.cpp b/gearsyncd/tests/cunit/TestRun.cpp
new file mode 100644
index 0000000000..ac6a735b01
--- /dev/null
+++ b/gearsyncd/tests/cunit/TestRun.cpp
@@ -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/gearsyncd/tests/cunit/TestRun.h b/gearsyncd/tests/cunit/TestRun.h
new file mode 100644
index 0000000000..51072f492a
--- /dev/null
+++ b/gearsyncd/tests/cunit/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/gearsyncd/tests/cunit/Util.c b/gearsyncd/tests/cunit/Util.c
new file mode 100644
index 0000000000..8e21922b9e
--- /dev/null
+++ b/gearsyncd/tests/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/gearsyncd/tests/cunit/Util.cpp b/gearsyncd/tests/cunit/Util.cpp
new file mode 100644
index 0000000000..8e21922b9e
--- /dev/null
+++ b/gearsyncd/tests/cunit/Util.cpp
@@ -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/gearsyncd/tests/cunit/Util.h b/gearsyncd/tests/cunit/Util.h
new file mode 100644
index 0000000000..c03085b45b
--- /dev/null
+++ b/gearsyncd/tests/cunit/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/gearsyncd/tests/testgearparser.cpp b/gearsyncd/tests/testgearparser.cpp
new file mode 100644
index 0000000000..e01c85bb19
--- /dev/null
+++ b/gearsyncd/tests/testgearparser.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2019 Broadcom Inc.
+ *
+ * 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.
+ */
+
+#include "gearboxparser.h"
+#include
+#include
+#include "cunit/Basic.h"
+#include "logger.h"
+
+void usage()
+{
+ std::cout << "Usage: testgearparser" << std::endl;
+}
+
+bool handleGearboxConfigFile(std::string file, bool warm);
+
+void positiveConfigTest()
+{
+ bool ret;
+
+ ret = handleGearboxConfigFile("tests/configs/positive/gearbox_config_1.json", false);
+ CU_ASSERT_EQUAL(ret, true);
+}
+
+void negativeConfigTest()
+{
+ bool ret;
+
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_invalid_array.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_invalid_json.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_phys.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_phy_id.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_phy_name.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_phy_address.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_phy_lib_name.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_phy_firmware_path.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_phy_config_file.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_phy_sai_init_config_file.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_phy_phy_access.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_phy_bus_id.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_invalid_phy_config_file.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_interfaces.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_ethernet_index.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_ethernet_phy_id.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_ethernet_line_lanes.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_ethernet_system_lanes.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_empty_ethernet_system_lanes.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_empty_ethernet_line_lanes.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+
+ //ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_ethernet_line_lane_speed.json", false);
+ //CU_ASSERT_EQUAL(ret, false);
+ //ret = handleGearboxConfigFile("tests/configs/negative/gearbox_config_missing_ethernet_system_lane_speed.json", false);
+ //CU_ASSERT_EQUAL(ret, false);
+}
+
+int unitTestMain()
+{
+ CU_pSuite pSuite = NULL;
+ CU_pTest pTest = NULL;
+ int ret = 0;
+
+ if (CUE_SUCCESS != CU_initialize_registry()) {
+ printf("%s: cunit failed to initialize registry\n", __FUNCTION__);
+ ret = CU_get_error();
+ } else {
+
+ CU_basic_set_mode(CU_BRM_VERBOSE);
+
+ // Run the tests and show the run summary
+ pSuite = CU_add_suite("gearbox_config_suite", 0, 0);
+ if (NULL == pSuite) {
+ printf("%s: cunit failed to create suite\n", __FUNCTION__);
+ CU_cleanup_registry();
+ ret = CU_get_error();
+ }
+ }
+
+ // Add the test to the suite
+ if (ret == 0) {
+ pTest = CU_add_test(pSuite, "gearbox_positive_config_test", positiveConfigTest);
+ if (pTest != NULL) {
+ pTest = CU_add_test(pSuite, "gearbox_negative_config_test", negativeConfigTest);
+ }
+
+ if (pTest == NULL) {
+ CU_cleanup_registry();
+ printf("%s: cunit failed to add test\n", __FUNCTION__);
+ ret = CU_get_error();
+ }
+ }
+
+ if (ret == 0) {
+ CU_basic_run_tests();
+ }
+ return ret;
+}
+
+bool handleGearboxConfigFile(std::string file, bool warm)
+{
+ GearboxParser p;
+ bool ret;
+
+ p.setWriteToDb(true);
+ p.setConfigPath(file);
+ ret = p.parse();
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ swss::Logger::linkToDbNative("testgearparser");
+
+ unitTestMain();
+ return 1;
+}
+
diff --git a/gearsyncd/tests/testphyparser.cpp b/gearsyncd/tests/testphyparser.cpp
new file mode 100644
index 0000000000..fa66680609
--- /dev/null
+++ b/gearsyncd/tests/testphyparser.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2019 Broadcom Inc.
+ *
+ * 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.
+ */
+
+#include "phyparser.h"
+#include
+#include
+#include "cunit/Basic.h"
+#include "logger.h"
+
+void usage()
+{
+ std::cout << "Usage: testphyparser" << std::endl;
+}
+
+bool handlePhyConfigFile(std::string file, bool warm);
+
+void positiveConfigTest()
+{
+ bool ret;
+
+ ret = handlePhyConfigFile("tests/configs/positive/phy1_config_1.json", false);
+ CU_ASSERT_EQUAL(ret, true);
+ ret = handlePhyConfigFile("tests/configs/positive/phy2_config_1.json", false);
+ CU_ASSERT_EQUAL(ret, true);
+}
+
+void negativeConfigTest()
+{
+ bool ret;
+
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_invalid_json.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_missing_lanes.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_lanes_missing_id.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_lanes_missing_system_side.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_lanes_missing_local_lane_id.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_lanes_missing_tx_polarity.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_lanes_missing_rx_polarity.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_lanes_missing_line_tx_lanemap.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_lanes_missing_line_rx_lanemap.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_lanes_missing_line_to_system_lanemap.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_lanes_missing_mdio_addr.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_id.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_mdio_addr.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_system_speed.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_system_fec.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_system_auto_neg.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_system_loopback.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_system_training.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_line_speed.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_line_fec.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_line_auto_neg.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_line_media_type.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_line_intf_type.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_line_loopback.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_line_training.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_line_adver_speed.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_line_adver_fec.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_line_adver_auto_neg.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_line_adver_asym_pause.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+ ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_line_adver_media_type.json", false);
+ CU_ASSERT_EQUAL(ret, false);
+
+ //ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_line_lanes.json", false);
+ //CU_ASSERT_EQUAL(ret, false);
+ //ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_line_lane_speed.json", false);
+ //CU_ASSERT_EQUAL(ret, false);
+ //ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_system_lanes.json", false);
+ //CU_ASSERT_EQUAL(ret, false);
+ //ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_missing_system_lane_speed.json", false);
+ //CU_ASSERT_EQUAL(ret, false);
+ //ret = handlePhyConfigFile("tests/configs/negative/phy_config_invalid_boolean.json", false);
+ //CU_ASSERT_EQUAL(ret, false);
+ //ret = handlePhyConfigFile("tests/configs/negative/phy_config_invalid_boolean2.json", false);
+ //CU_ASSERT_EQUAL(ret, false);
+ //ret = handlePhyConfigFile("tests/configs/negative/phy_config_missing_address.json", false);
+ //CU_ASSERT_EQUAL(ret, false);
+ //ret = handlePhyConfigFile("tests/configs/negative/phy_config_invalid_array.json", false);
+ //CU_ASSERT_EQUAL(ret, false);
+ //ret = handlePhyConfigFile("tests/configs/negative/phy_config_missing_mode.json", false);
+ //CU_ASSERT_EQUAL(ret, false);
+ //ret = handlePhyConfigFile("tests/configs/negative/phy_config_missing_name.json", false);
+ //CU_ASSERT_EQUAL(ret, false);
+ //ret = handlePhyConfigFile("tests/configs/negative/phy_config_missing_port_ref_clk.json", false);
+ //CU_ASSERT_EQUAL(ret, false);
+ //ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_empty_line_lanes.json", false);
+ //CU_ASSERT_EQUAL(ret, false);
+ //ret = handlePhyConfigFile("tests/configs/negative/phy_config_ports_empty_system_lanes.json", false);
+ //CU_ASSERT_EQUAL(ret, false);
+}
+
+int unitTestMain()
+{
+ CU_pSuite pSuite = NULL;
+ CU_pTest pTest = NULL;
+ int ret = 0;
+
+ if (CUE_SUCCESS != CU_initialize_registry()) {
+ printf("%s: cunit failed to initialize registry\n", __FUNCTION__);
+ ret = CU_get_error();
+ } else {
+
+ CU_basic_set_mode(CU_BRM_VERBOSE);
+
+ // Run the tests and show the run summary
+ pSuite = CU_add_suite("phy_config_suite", 0, 0);
+ if (NULL == pSuite) {
+ printf("%s: cunit failed to create suite\n", __FUNCTION__);
+ CU_cleanup_registry();
+ ret = CU_get_error();
+ }
+ }
+
+ // Add the test to the suite
+ if (ret == 0) {
+ pTest = CU_add_test(pSuite, "phy_positive_config_test", positiveConfigTest);
+
+ if (pTest != NULL) {
+ pTest = CU_add_test(pSuite, "phy_negative_config_test", negativeConfigTest);
+ }
+
+ if (pTest == NULL) {
+ CU_cleanup_registry();
+ printf("%s: cunit failed to add test\n", __FUNCTION__);
+ ret = CU_get_error();
+ }
+ }
+ if (ret == 0) {
+ CU_basic_run_tests();
+ }
+ return ret;
+}
+
+bool handlePhyConfigFile(std::string file, bool warm)
+{
+ PhyParser p;
+ bool ret;
+
+ p.setWriteToDb(true);
+ p.setConfigPath(file);
+ ret = p.parse();
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ swss::Logger::linkToDbNative("testphyparser");
+
+ unitTestMain();
+ return 1;
+}
+
diff --git a/lib/gearboxutils.cpp b/lib/gearboxutils.cpp
new file mode 100644
index 0000000000..bcdd9e2896
--- /dev/null
+++ b/lib/gearboxutils.cpp
@@ -0,0 +1,459 @@
+/*
+ * Copyright 2019-2020 Broadcom Inc.
+ *
+ * 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.
+ */
+
+#include "gearboxutils.h"
+
+namespace swss {
+
+std::tuple GearboxUtils::parseGearboxKey(std::string key_str)
+{
+ /*
+ * The Gearbox key string has a few formats based on the number of tokens.
+ * Parse and return accordingly;
+ * phy::ports: rtn: ports
+ * phy::lanes: rtn: lanes
+ * phy: rtn: phy
+ * interface: rtn: interface
+ */
+
+ std::string str1, str2, str3;
+ std::vector token = tokenize(key_str, ':');
+
+ if (token.size() == 4)
+ {
+ str1 = token.at(2);
+ str2 = token.at(1);
+ str3 = token.at(3);
+ }
+ else if (token.size() == 2)
+ {
+ str1 = token.at(0);
+ str2 = token.at(1);
+ }
+
+ SWSS_LOG_DEBUG("Parsed key:%s, Return:(%s)(%s)(%s)", key_str.c_str(), str1.c_str(), str2.c_str(), str3.c_str());
+
+ return make_tuple(str1, str2, str3);
+}
+
+bool GearboxUtils::platformHasGearbox()
+{
+ bool ret = false;
+
+ if (access("/usr/share/sonic/hwsku/gearbox_config.json", F_OK) != -1)
+ {
+ ret = true;
+ }
+ return ret;
+}
+
+bool GearboxUtils::isGearboxConfigDone(Table &gearboxTable)
+{
+ std::vector tuples;
+ bool gearboxConfigDone = false;
+
+ // this will return false if GearboxConfigDone is not set in the database
+
+ gearboxConfigDone = gearboxTable.get("GearboxConfigDone", tuples);
+ return gearboxConfigDone;
+}
+
+bool GearboxUtils::isGearboxConfigDone(Table *gearboxTable)
+{
+ std::vector tuples;
+ bool gearboxConfigDone = false;
+
+ // this will return false if GearboxConfigDone is not set in the database
+
+ gearboxConfigDone = gearboxTable->get("GearboxConfigDone", tuples);
+ return gearboxConfigDone;
+}
+
+bool GearboxUtils::isGearboxEnabled(Table *gearboxTable)
+{
+ int count = 10; // 10 seconds is more than enough time
+ bool gearboxDone = false;
+
+ SWSS_LOG_ENTER();
+
+ if (platformHasGearbox() != true)
+ {
+ return gearboxDone;
+ }
+
+ // wait until gearbox table is ready
+ while (count > 0)
+ {
+ if (!isGearboxConfigDone(gearboxTable))
+ {
+ sleep(1);
+ count--;
+ continue;
+ }
+ else
+ {
+ gearboxDone = true;
+ break;
+ }
+ }
+
+ return gearboxDone;
+}
+
+std::map GearboxUtils::loadPhyMap(Table *gearboxTable)
+{
+ std::vector ovalues;
+ std::tuple keyt;
+ std::vector keys;
+
+ SWSS_LOG_ENTER();
+
+ gearboxTable->getKeys(keys);
+
+ if (keys.empty())
+ {
+ SWSS_LOG_ERROR("No Gearbox records in ApplDB!");
+ return gearboxPhyMap;
+ }
+
+ for (auto &k : keys)
+ {
+ keyt = parseGearboxKey(k);
+
+ if (std::get<0>(keyt).compare("phy") == 0)
+ {
+ gearbox_phy_t phy = {};
+
+ gearboxTable->get(k, ovalues);
+ for (auto &val : ovalues)
+ {
+ if (val.first == "phy_id")
+ {
+ phy.phy_id = std::stoi(val.second);
+ }
+ else if (val.first == "phy_oid")
+ {
+ // oid is from create_switch (not config)
+ phy.phy_oid = val.second;
+ }
+ else if (val.first == "name")
+ {
+ phy.name = val.second;
+ }
+ else if (val.first == "lib_name")
+ {
+ phy.lib_name = val.second;
+ }
+ else if (val.first == "firmware_path")
+ {
+ phy.firmware = val.second;
+ }
+ else if (val.first == "config_file")
+ {
+ phy.config_file = val.second;
+ }
+ else if (val.first == "sai_init_config_file")
+ {
+ phy.sai_init_config_file = val.second;
+ }
+ else if (val.first == "phy_access")
+ {
+ phy.access = val.second;
+ }
+ else if (val.first == "address")
+ {
+ phy.address = std::stoi(val.second);
+ }
+ else if (val.first == "bus_id")
+ {
+ phy.bus_id = std::stoi(val.second);
+ }
+ }
+ gearboxPhyMap[phy.phy_id] = phy;
+ }
+ }
+
+ return gearboxPhyMap;
+}
+
+std::map GearboxUtils::loadInterfaceMap(Table *gearboxTable)
+{
+ std::vector ovalues;
+ std::tuple keyt;
+ std::vector keys;
+
+ SWSS_LOG_ENTER();
+
+ gearboxTable->getKeys(keys);
+
+ if (keys.empty())
+ {
+ SWSS_LOG_ERROR("No Gearbox records in ApplDB!");
+ return gearboxInterfaceMap;
+ }
+
+ for (auto &k : keys)
+ {
+ keyt = parseGearboxKey(k);
+
+ if (std::get<0>(keyt).compare("interface") == 0)
+ {
+ gearbox_interface_t interface = {};
+
+ gearboxTable->get(k, ovalues);
+ for (auto &val : ovalues)
+ {
+ if (val.first == "index")
+ {
+ interface.index = std::stoi(val.second);
+ SWSS_LOG_DEBUG("BOX interface = %d", interface.index);
+ }
+ else if (val.first == "phy_id")
+ {
+ interface.phy_id = std::stoi(val.second);
+ SWSS_LOG_DEBUG("BOX phy_id = %d", interface.phy_id);
+ }
+ else if (val.first == "line_lanes")
+ {
+ std::stringstream ss(val.second);
+
+ for (int i; ss >> i;)
+ {
+ SWSS_LOG_DEBUG("Parsed key:%s, val:%s,inserted %d", val.first.c_str(), val.second.c_str(), i);
+ interface.line_lanes.insert(i);
+ if (ss.peek() == ',')
+ {
+ ss.ignore();
+ }
+ }
+ }
+ else if (val.first == "system_lanes")
+ {
+ std::stringstream ss(val.second);
+
+ for (int i; ss >> i;)
+ {
+ SWSS_LOG_DEBUG("Parsed key:%s, val:%s,inserted %d", val.first.c_str(), val.second.c_str(), i);
+ interface.system_lanes.insert(i);
+ if (ss.peek() == ',')
+ {
+ ss.ignore();
+ }
+ }
+ }
+ }
+ gearboxInterfaceMap[interface.index] = interface;
+ }
+ }
+
+ return gearboxInterfaceMap;
+}
+
+std::map GearboxUtils::loadLaneMap(Table *gearboxTable)
+{
+ std::vector ovalues;
+ std::tuple keyt;
+ std::vector keys;
+
+ SWSS_LOG_ENTER();
+
+ gearboxTable->getKeys(keys);
+
+ if (keys.empty())
+ {
+ SWSS_LOG_ERROR("No Gearbox records in ApplDB!");
+ return gearboxLaneMap;
+ }
+
+ for (auto &k : keys)
+ {
+ keyt = parseGearboxKey(k);
+
+ if (std::get<0>(keyt).compare("lanes") == 0)
+ {
+ gearbox_lane_t lane = {};
+
+ gearboxTable->get(k, ovalues);
+ for (auto &val : ovalues)
+ {
+ if (val.first == "index")
+ {
+ lane.index = std::stoi(val.second);
+ }
+ else if (val.first == "tx_polarity")
+ {
+ lane.tx_polarity = std::stoi(val.second);
+ }
+ else if (val.first == "rx_polarity")
+ {
+ lane.rx_polarity = std::stoi(val.second);
+ }
+ else if (val.first == "line_tx_lanemap")
+ {
+ lane.line_tx_lanemap = std::stoi(val.second);
+ }
+ else if (val.first == "line_rx_lanemap")
+ {
+ lane.line_rx_lanemap = std::stoi(val.second);
+ }
+ else if (val.first == "line_to_system_lanemap")
+ {
+ lane.line_to_system_lanemap = std::stoi(val.second);
+ }
+ else if (val.first == "mdio_addr")
+ {
+ lane.mdio_addr = val.second;
+ }
+ else if (val.first == "system_side")
+ {
+ lane.system_side = (val.second == "true") ? true : false;
+ }
+ }
+ gearboxLaneMap[lane.index] = lane;
+ }
+ }
+
+ return gearboxLaneMap;
+}
+
+std::map GearboxUtils::loadPortMap(Table *gearboxTable)
+{
+ std::vector ovalues;
+ std::tuple keyt;
+ std::vector keys;
+
+ SWSS_LOG_ENTER();
+
+ gearboxTable->getKeys(keys);
+
+ if (keys.empty())
+ {
+ SWSS_LOG_ERROR("No Gearbox records in ApplDB!");
+ return gearboxPortMap;
+ }
+
+ for (auto &k : keys)
+ {
+ keyt = parseGearboxKey(k);
+
+ if (std::get<0>(keyt).compare("ports") == 0)
+ {
+ gearbox_port_t port = {};
+
+ gearboxTable->get(k, ovalues);
+ for (auto &val : ovalues)
+ {
+ if (val.first == "index")
+ {
+ port.index = std::stoi(val.second);
+ }
+ else if (val.first == "mdio_addr")
+ {
+ port.mdio_addr = val.second;
+ }
+ else if (val.first == "system_speed")
+ {
+ port.system_speed = std::stoi(val.second);
+ }
+ else if (val.first == "system_fec")
+ {
+ port.system_fec = val.second;
+ }
+ else if (val.first == "system_auto_neg")
+ {
+ port.system_auto_neg = (val.second == "true") ? true : false;
+ }
+ else if (val.first == "system_loopback")
+ {
+ port.system_loopback = val.second;
+ }
+ else if (val.first == "system_training")
+ {
+ port.system_training = (val.second == "true") ? true : false;
+ }
+ else if (val.first == "line_speed")
+ {
+ port.line_speed = std::stoi(val.second);
+ }
+ else if (val.first == "line_fec")
+ {
+ port.line_fec = val.second;
+ }
+ else if (val.first == "line_auto_neg")
+ {
+ port.line_auto_neg = (val.second == "true") ? true : false;
+ }
+ else if (val.first == "line_media_type")
+ {
+ port.line_media_type = val.second;
+ }
+ else if (val.first == "line_intf_type")
+ {
+ port.line_intf_type = val.second;
+ }
+ else if (val.first == "line_loopback")
+ {
+ port.line_loopback = val.second;
+ }
+ else if (val.first == "line_training")
+ {
+ port.line_training = (val.second == "true") ? true : false;
+ }
+ else if (val.first == "line_adver_speed")
+ {
+ std::stringstream ss(val.second);
+ for (int i; ss >> i;)
+ {
+ port.line_adver_speed.insert(i);
+ if (ss.peek() == ',')
+ {
+ ss.ignore();
+ }
+ }
+ }
+ else if (val.first == "line_adver_fec")
+ {
+ std::stringstream ss(val.second);
+ for (int i; ss >> i;)
+ {
+ port.line_adver_fec.insert(i);
+ if (ss.peek() == ',')
+ {
+ ss.ignore();
+ }
+ }
+ }
+ else if (val.first == "line_adver_auto_neg")
+ {
+ port.line_adver_auto_neg = (val.second == "true") ? true : false;
+ }
+ else if (val.first == "line_adver_asym_pause")
+ {
+ port.line_adver_asym_pause = (val.second == "true") ? true : false;
+ }
+ else if (val.first == "line_adver_media_type")
+ {
+ port.line_adver_media_type = val.second;
+ }
+ }
+ gearboxPortMap[port.index] = port;
+ }
+ }
+
+ return gearboxPortMap;
+}
+
+}
diff --git a/lib/gearboxutils.h b/lib/gearboxutils.h
new file mode 100644
index 0000000000..e8ffc85c96
--- /dev/null
+++ b/lib/gearboxutils.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2019-2020 Broadcom Inc.
+ *
+ * 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.
+ */
+
+#ifndef SWSS_COMMON_GEARBOX_UTILS_H
+#define SWSS_COMMON_GEARBOX_UTILS_H
+
+#include
+#include
+#include
+#include
+#include