diff --git a/CMakeLists.txt b/CMakeLists.txt index 44d5ed5..8c51df9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,4 +56,7 @@ daq_add_application(print_detailed_config_info print_detailed_config_info.cxx TEST LINK_LIBRARIES appmodel_dal confmodel::confmodel conffwk::conffwk logging::logging) +daq_add_unit_test(ConfigObjectFactory_test LINK_LIBRARIES + confmodel::confmodel_dal conffwk::conffwk appmodel_dal) + daq_install() diff --git a/src/ConfigObjectFactory.cpp b/src/ConfigObjectFactory.cpp index 1ac24be..c44ba94 100644 --- a/src/ConfigObjectFactory.cpp +++ b/src/ConfigObjectFactory.cpp @@ -1,5 +1,6 @@ #include "ConfigObjectFactory.hpp" +#include "appmodel/appmodelIssues.hpp" #include "confmodel/Service.hpp" #include "oks/file.hpp" @@ -33,6 +34,9 @@ ConfigObjectFactory::create(const std::string& class_name, //--- conffwk::ConfigObject ConfigObjectFactory::create_queue_obj(const QueueDescriptor* qdesc, std::string uid) const { + if (qdesc == nullptr) { + throw (BadConf(ERS_HERE, "QueueDescriptor pointer is null")); + } std::string queue_uid(qdesc->get_uid_base() + uid); auto queue_obj = create("Queue", queue_uid); @@ -46,6 +50,10 @@ ConfigObjectFactory::create_queue_obj(const QueueDescriptor* qdesc, std::string //--- conffwk::ConfigObject ConfigObjectFactory::create_queue_sid_obj(const QueueDescriptor* qdesc, uint32_t src_id) const { + if (qdesc == nullptr) { + throw (BadConf(ERS_HERE, "QueueDescriptor pointer is null")); + } + std::string queue_uid(fmt::format("{}{}", qdesc->get_uid_base(), src_id)); auto queue_obj = create("QueueWithSourceId", queue_uid); @@ -68,6 +76,9 @@ return create_queue_sid_obj(qdesc, stream->get_source_id()); conffwk::ConfigObject ConfigObjectFactory::create_callback_sid_obj(const DataMoveCallbackDescriptor* cdesc, uint32_t src_id) const { + if (cdesc == nullptr) { + throw (BadConf(ERS_HERE, "DataMoveCallbackDescriptor pointer is null")); + } std::string rdc_uid(fmt::format("{}{}", cdesc->get_uid_base(), src_id)); auto rdc_obj = create("DataMoveCallbackConf", rdc_uid); @@ -89,7 +100,9 @@ ConfigObjectFactory::create_callback_sid_obj(const DataMoveCallbackDescriptor* c conffwk::ConfigObject ConfigObjectFactory::create_net_obj(const NetworkConnectionDescriptor* ndesc, std::string app_uid) const { - + if (ndesc == nullptr) { + throw (BadConf(ERS_HERE, "NetworkConnectionDescriptor pointer is null")); + } auto svc_obj = ndesc->get_associated_service()->config_object(); std::string net_id = ndesc->get_uid_base() + app_uid; auto net_obj = create("NetworkConnection", net_id); diff --git a/unittest/ConfigObjectFactory_test.cxx b/unittest/ConfigObjectFactory_test.cxx new file mode 100644 index 0000000..24936bc --- /dev/null +++ b/unittest/ConfigObjectFactory_test.cxx @@ -0,0 +1,198 @@ +/** + * @file ConfigObjectFactory_test.cxx Unit Tests for ConfigObjectFactory + * + * This is part of the DUNE DAQ Application Framework, copyright 2025. + * Licensing/copyright details are in the COPYING file that you should have + * received with this code. + */ + +#define BOOST_TEST_MODULE config_object_factory // NOLINT + +#include "boost/test/unit_test.hpp" + +#include "../src/ConfigObjectFactory.hpp" // NOLINT +#include "appmodel/DataMoveCallbackConf.hpp" +#include "appmodel/DFOApplication.hpp" +#include "appmodel/NetworkConnectionDescriptor.hpp" +#include "appmodel/QueueDescriptor.hpp" +#include "conffwk/Configuration.hpp" +#include "confmodel/QueueWithSourceId.hpp" + +#include +#include +#include +#include +#include + +using namespace dunedaq; +using namespace dunedaq::appmodel; + +struct fact { + fact() : confdb("oksconflibs") { + oksfile = std::tmpnam(nullptr); + confdb.create(oksfile, includes); + // ConfigObjectFactory constructor needs a smart daq app so + // arbitrarily create a DFOApplication + confdb.create(oksfile, "DFOApplication", app_name, conf_obj); + dfo = confdb.get(conf_obj); + } + + ~fact() { + std::remove(oksfile.c_str()); + } + + std::string oksfile; + conffwk::Configuration confdb; + const std::list includes{ + "schema/confmodel/dunedaq.schema.xml", + "schema/appmodel/application.schema.xml"}; + const std::string app_name{"DFO-01"}; + conffwk::ConfigObject conf_obj; + const DFOApplication* dfo; +}; + + +BOOST_FIXTURE_TEST_SUITE(ConfigObjectFactory_test, fact) + +BOOST_AUTO_TEST_CASE(simple_create){ + ConfigObjectFactory factory(dfo); + + auto obj = factory.create("Queue", "wibble"); + BOOST_CHECK(!obj.is_null()); + BOOST_CHECK(obj.UID() == "wibble"); +} + +BOOST_AUTO_TEST_CASE(simple_get_dal){ + ConfigObjectFactory factory(dfo); + + auto obj = factory.create("Queue", "wibble"); + BOOST_CHECK(!obj.is_null()); + BOOST_CHECK(obj.UID() == "wibble"); + + auto dal_obj = factory.get_dal("wibble"); + BOOST_CHECK(dal_obj != nullptr); + BOOST_CHECK(dal_obj->UID() == "wibble"); + + dal_obj = factory.get_dal(obj); + BOOST_CHECK(dal_obj != nullptr); + BOOST_CHECK(dal_obj->UID() == "wibble"); +} + +BOOST_AUTO_TEST_CASE(bad_descriptor){ + ConfigObjectFactory factory(dfo); + + QueueDescriptor* qdesc{nullptr}; + conffwk::ConfigObject cobj; + BOOST_CHECK_THROW(cobj = factory.create_queue_obj(qdesc, "bad"), BadConf); + BOOST_CHECK_THROW(cobj = factory.create_queue_sid_obj(qdesc, 123), BadConf); + auto stream_obj = factory.create("DetectorStream", "stream"); + stream_obj.set_by_val("source_id", 1234); + auto stream_dal = confdb.get(stream_obj); + BOOST_CHECK_THROW(cobj = factory.create_queue_sid_obj(qdesc, stream_dal), BadConf); + + NetworkConnectionDescriptor* ndesc{nullptr}; + BOOST_CHECK_THROW(cobj = factory.create_net_obj(ndesc, "conn1"), BadConf); + BOOST_CHECK_THROW(cobj = factory.create_net_obj(ndesc), BadConf); + + DataMoveCallbackDescriptor* cdesc{nullptr}; + BOOST_CHECK_THROW(cobj = factory.create_callback_sid_obj(cdesc, 123), BadConf); +} + +BOOST_AUTO_TEST_CASE(qdescriptor){ + ConfigObjectFactory factory(dfo); + + auto qdesc_obj = factory.create("QueueDescriptor", "qdesc"); + qdesc_obj.set_by_val("data_type", "test_type"); + qdesc_obj.set_by_val("uid_base", "test_uid"); + auto qd_dal = confdb.get(qdesc_obj); + + auto qobj = factory.create_queue_obj(qd_dal); + BOOST_CHECK(!qobj.is_null()); + BOOST_CHECK(qobj.UID() == "test_uid"); + + auto qobj1 = factory.create_queue_obj(qd_dal, "77"); + BOOST_CHECK(!qobj1.is_null()); + BOOST_CHECK(qobj1.UID() == "test_uid77"); +} + +BOOST_AUTO_TEST_CASE(qsid_descriptor){ + ConfigObjectFactory factory(dfo); + + auto qdesc_obj = factory.create("QueueDescriptor", "qdesc"); + qdesc_obj.set_by_val("data_type", "test_type"); + qdesc_obj.set_by_val("uid_base", "test_uid"); + auto qd_dal = confdb.get(qdesc_obj); + + auto qobj = factory.create_queue_sid_obj(qd_dal, 1234); + BOOST_CHECK(!qobj.is_null()); + BOOST_CHECK(qobj.UID() == "test_uid1234"); + auto qdal = confdb.get(qobj); + BOOST_CHECK (qdal->get_source_id() == 1234); +} + +BOOST_AUTO_TEST_CASE(callback_sid_descriptor){ + ConfigObjectFactory factory(dfo); + + auto cdesc_obj = factory.create("DataMoveCallbackDescriptor", "cdesc"); + cdesc_obj.set_by_val("data_type", "test_type"); + cdesc_obj.set_by_val("uid_base", "test_uid"); + auto cdesc_dal = confdb.get(cdesc_obj); + + auto cobj = factory.create_callback_sid_obj(cdesc_dal, 1234); + BOOST_CHECK(!cobj.is_null()); + BOOST_CHECK(cobj.UID() == "test_uid1234"); + auto cdal = confdb.get(cobj); + BOOST_CHECK (cdal->get_source_id() == 1234); +} + +BOOST_AUTO_TEST_CASE(qsid_stream_descriptor){ + ConfigObjectFactory factory(dfo); + + auto qdesc_obj = factory.create("QueueDescriptor", "qdesc"); + qdesc_obj.set_by_val("data_type", "test_type"); + qdesc_obj.set_by_val("uid_base", "test_uid"); + auto qd_dal = confdb.get(qdesc_obj); + + auto stream_obj = factory.create("DetectorStream", "stream"); + stream_obj.set_by_val("source_id", 1234); + auto stream_dal = confdb.get(stream_obj); + + auto qobj = factory.create_queue_sid_obj(qd_dal, stream_dal); + BOOST_CHECK(!qobj.is_null()); + BOOST_CHECK(qobj.UID() == "test_uid1234"); + auto qdal = confdb.get(qobj); + BOOST_CHECK (qdal->get_source_id() == 1234); +} + +BOOST_AUTO_TEST_CASE(network_connection){ + ConfigObjectFactory factory(dfo); + + auto svc_obj = factory.create("Service", "svc-1"); + + auto ndesc_obj = factory.create("NetworkConnectionDescriptor", "ndesc"); + ndesc_obj.set_by_val("data_type", "test_type"); + ndesc_obj.set_by_val("uid_base", "test-net"); + ndesc_obj.set_obj("associated_service", &svc_obj); + auto nd_dal = confdb.get(ndesc_obj); + + auto net_obj = factory.create_net_obj(nd_dal, "conn1"); + BOOST_CHECK(!net_obj.is_null()); + BOOST_CHECK(net_obj.UID() == "test-netconn1"); + + net_obj = factory.create_net_obj(nd_dal); + BOOST_CHECK(!net_obj.is_null()); + BOOST_CHECK(net_obj.UID() == "test-net"+app_name); +} + +BOOST_AUTO_TEST_CASE(module_update){ + ConfigObjectFactory factory(dfo); + + BOOST_CHECK(dfo->get_modules().size() == 0); + auto mod = factory.create("DFOModule", "mod-1"); + std::vector modules{ + confdb.get(mod)}; + factory.update_modules(modules); + BOOST_CHECK(dfo->get_modules().size() == 1); +} + +BOOST_AUTO_TEST_SUITE_END()