From 39121566e0af94d6e64024d7c663fedba83a901d Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Thu, 19 Oct 2023 21:08:00 +0200 Subject: [PATCH] Allow ESHandle be constructed from a whyFailedFactory of another ESHandle --- FWCore/Framework/interface/ESHandle.h | 6 +- FWCore/Framework/test/BuildFile.xml | 5 + FWCore/Framework/test/test_catch2_ESHandle.cc | 221 ++++++++++++++++++ 3 files changed, 229 insertions(+), 3 deletions(-) create mode 100644 FWCore/Framework/test/test_catch2_ESHandle.cc diff --git a/FWCore/Framework/interface/ESHandle.h b/FWCore/Framework/interface/ESHandle.h index 0152dcb6207f6..26c3462942d9a 100644 --- a/FWCore/Framework/interface/ESHandle.h +++ b/FWCore/Framework/interface/ESHandle.h @@ -37,7 +37,7 @@ namespace edm { : data_(iData), description_(desc) {} ///Used when the attempt to get the data failed - ESHandleBase(std::shared_ptr&& iWhyFailed) : whyFailedFactory_(std::move(iWhyFailed)) {} + ESHandleBase(std::shared_ptr iWhyFailed) : whyFailedFactory_(std::move(iWhyFailed)) {} edm::eventsetup::ComponentDescription const* description() const; @@ -80,7 +80,7 @@ namespace edm { ESHandle() = default; ESHandle(T const* iData) : ESHandleBase(iData, nullptr) {} ESHandle(T const* iData, edm::eventsetup::ComponentDescription const* desc) : ESHandleBase(iData, desc) {} - ESHandle(std::shared_ptr&&); + ESHandle(std::shared_ptr); // ---------- const member functions --------------------- T const* product() const { return static_cast(productStorage()); } @@ -93,7 +93,7 @@ namespace edm { }; template - ESHandle::ESHandle(std::shared_ptr&& iWhyFailed) + ESHandle::ESHandle(std::shared_ptr iWhyFailed) : ESHandleBase(std::move(iWhyFailed)) {} // Free swap function diff --git a/FWCore/Framework/test/BuildFile.xml b/FWCore/Framework/test/BuildFile.xml index 59078d9979902..f3800f5060954 100644 --- a/FWCore/Framework/test/BuildFile.xml +++ b/FWCore/Framework/test/BuildFile.xml @@ -350,6 +350,11 @@ + + + + + diff --git a/FWCore/Framework/test/test_catch2_ESHandle.cc b/FWCore/Framework/test/test_catch2_ESHandle.cc new file mode 100644 index 0000000000000..652e04768475d --- /dev/null +++ b/FWCore/Framework/test/test_catch2_ESHandle.cc @@ -0,0 +1,221 @@ +#include "catch.hpp" + +#include "FWCore/Framework/interface/ESHandle.h" +#include "FWCore/Utilities/interface/EDMException.h" + +namespace { + class TestExceptionFactory : public edm::ESHandleExceptionFactory { + public: + std::exception_ptr make() const override { return std::make_exception_ptr(edm::Exception(edm::errors::OtherCMS)); } + }; +} // namespace + +TEST_CASE("test edm::ESHandle", "[ESHandle]") { + SECTION("Default constructor") { + edm::ESHandle handle; + REQUIRE(not handle.isValid()); + REQUIRE(not handle.failedToGet()); + REQUIRE_THROWS_AS(handle.description(), edm::Exception); + REQUIRE(handle.product() == nullptr); + } + + SECTION("Valid construction") { + int const value = 42; + + SECTION("without ComponentDescription") { + edm::ESHandle handle(&value); + REQUIRE(not handle.isValid()); + REQUIRE(not handle.failedToGet()); + REQUIRE_THROWS_AS(handle.description(), edm::Exception); + REQUIRE(handle.product() != nullptr); + REQUIRE(*handle == value); + } + + SECTION("Valid construction, with ComponentDescription") { + edm::eventsetup::ComponentDescription const desc; + edm::ESHandle handle(&value, &desc); + REQUIRE(handle.isValid()); + REQUIRE(not handle.failedToGet()); + REQUIRE(handle.description() == &desc); + REQUIRE(handle.product() != nullptr); + REQUIRE(*handle == value); + } + } + + SECTION("Construction for a 'failure'") { + SECTION("From temporary factory object") { + edm::ESHandle handle(std::make_shared()); + REQUIRE(not handle.isValid()); + REQUIRE(handle.failedToGet()); + REQUIRE_THROWS_AS(handle.description(), edm::Exception); + REQUIRE_THROWS_AS(handle.product(), edm::Exception); + } + + SECTION("From another factory object") { + auto const factory = std::make_shared(); + edm::ESHandle handle(factory); + REQUIRE(not handle.isValid()); + REQUIRE(handle.failedToGet()); + REQUIRE_THROWS_AS(handle.description(), edm::Exception); + REQUIRE_THROWS_AS(handle.product(), edm::Exception); + REQUIRE(handle.whyFailedFactory().get() == factory.get()); + } + + SECTION("From another ESHandle") { + auto const factory = std::make_shared(); + edm::ESHandle handleA(factory); + edm::ESHandle handle(handleA.whyFailedFactory()); + REQUIRE(not handle.isValid()); + REQUIRE(handle.failedToGet()); + REQUIRE_THROWS_AS(handle.description(), edm::Exception); + REQUIRE_THROWS_AS(handle.product(), edm::Exception); + REQUIRE(handle.whyFailedFactory().get() == factory.get()); + } + } + + SECTION("Copying") { + int const valueA = 42; + edm::eventsetup::ComponentDescription const descA; + + SECTION("From valid ESHandle") { + edm::ESHandle const handleA(&valueA, &descA); + + SECTION("Constructor") { + edm::ESHandle handleB(handleA); + REQUIRE(handleA.isValid()); + REQUIRE(*handleA == valueA); + REQUIRE(handleB.isValid()); + REQUIRE(*handleB == valueA); + } + + SECTION("Assignment") { + edm::ESHandle handleB; + REQUIRE(not handleB.isValid()); + + handleB = handleA; + REQUIRE(handleA.isValid()); + REQUIRE(*handleA == valueA); + REQUIRE(handleB.isValid()); + REQUIRE(*handleB == valueA); + } + } + + SECTION("From invalid ESHandle") { + edm::ESHandle const handleA(std::make_shared()); + + SECTION("Constructor") { + edm::ESHandle handleB(handleA); + REQUIRE(not handleA.isValid()); + REQUIRE(handleA.failedToGet()); + REQUIRE_THROWS_AS(handleA.description(), edm::Exception); + REQUIRE_THROWS_AS(handleA.product(), edm::Exception); + + REQUIRE(not handleB.isValid()); + REQUIRE(handleB.failedToGet()); + REQUIRE_THROWS_AS(handleB.description(), edm::Exception); + REQUIRE_THROWS_AS(handleB.product(), edm::Exception); + } + + SECTION("Assignment") { + edm::ESHandle handleB(&valueA, &descA); + REQUIRE(handleB.isValid()); + + handleB = handleA; + REQUIRE(not handleA.isValid()); + REQUIRE(handleA.failedToGet()); + REQUIRE_THROWS_AS(handleA.description(), edm::Exception); + REQUIRE_THROWS_AS(handleA.product(), edm::Exception); + + REQUIRE(not handleB.isValid()); + REQUIRE(handleB.failedToGet()); + REQUIRE_THROWS_AS(handleB.description(), edm::Exception); + REQUIRE_THROWS_AS(handleB.product(), edm::Exception); + } + } + } + + SECTION("Moving") { + int const valueA = 42; + edm::eventsetup::ComponentDescription const descA; + + SECTION("From valid ESHandle") { + edm::ESHandle handleA(&valueA, &descA); + + SECTION("Constructor") { + edm::ESHandle handleB(std::move(handleA)); + REQUIRE(handleB.isValid()); + REQUIRE(*handleB == valueA); + } + + SECTION("Assignment") { + edm::ESHandle handleB; + REQUIRE(not handleB.isValid()); + + handleB = std::move(handleA); + REQUIRE(handleB.isValid()); + REQUIRE(*handleB == valueA); + } + } + + SECTION("From invalid ESHandle") { + edm::ESHandle handleA(std::make_shared()); + + SECTION("Constructor") { + edm::ESHandle handleB(std::move(handleA)); + // this is pretty much the only feature that we can test on + // the moved-from ESHandle that is guaranteed to change (to + // test that move actually happens instead of copy) + REQUIRE(not handleA.failedToGet()); + + REQUIRE(not handleB.isValid()); + REQUIRE(handleB.failedToGet()); + REQUIRE_THROWS_AS(handleB.description(), edm::Exception); + REQUIRE_THROWS_AS(handleB.product(), edm::Exception); + } + + SECTION("Assignment") { + edm::ESHandle handleB(&valueA, &descA); + REQUIRE(handleB.isValid()); + + handleB = std::move(handleA); + // this is pretty much the only feature that we can test on + // the moved-from ESHandle that is guaranteed to change (to + // test that move actually happens instead of copy) + REQUIRE(not handleA.failedToGet()); + + REQUIRE(not handleB.isValid()); + REQUIRE(handleB.failedToGet()); + REQUIRE_THROWS_AS(handleB.description(), edm::Exception); + REQUIRE_THROWS_AS(handleB.product(), edm::Exception); + } + } + } + + SECTION("Swap") { + int const valueA = 42; + edm::eventsetup::ComponentDescription const descA; + edm::ESHandle handleA(&valueA, &descA); + + SECTION("With value") { + int const valueB = 3; + edm::ESHandle handleB(&valueB); + + std::swap(handleA, handleB); + REQUIRE(not handleA.isValid()); + REQUIRE(handleB.isValid()); + REQUIRE(*handleB == valueA); + } + + SECTION("With failure factory") { + auto factory = std::make_shared(); + edm::ESHandle handleB(factory); + + std::swap(handleA, handleB); + REQUIRE(not handleA.isValid()); + REQUIRE(handleA.failedToGet()); + REQUIRE(handleA.whyFailedFactory().get() == factory.get()); + REQUIRE(handleB.isValid()); + REQUIRE(*handleB == valueA); + } + } +}