Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow ESHandle be constructed from a whyFailedFactory of another ESHandle #43068

Merged
merged 1 commit into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions FWCore/Framework/interface/ESHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace edm {
: data_(iData), description_(desc) {}

///Used when the attempt to get the data failed
ESHandleBase(std::shared_ptr<ESHandleExceptionFactory>&& iWhyFailed) : whyFailedFactory_(std::move(iWhyFailed)) {}
ESHandleBase(std::shared_ptr<ESHandleExceptionFactory> iWhyFailed) : whyFailedFactory_(std::move(iWhyFailed)) {}

edm::eventsetup::ComponentDescription const* description() const;

Expand Down Expand Up @@ -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<ESHandleExceptionFactory>&&);
ESHandle(std::shared_ptr<ESHandleExceptionFactory>);

// ---------- const member functions ---------------------
T const* product() const { return static_cast<T const*>(productStorage()); }
Expand All @@ -93,7 +93,7 @@ namespace edm {
};

template <class T>
ESHandle<T>::ESHandle(std::shared_ptr<edm::ESHandleExceptionFactory>&& iWhyFailed)
ESHandle<T>::ESHandle(std::shared_ptr<edm::ESHandleExceptionFactory> iWhyFailed)
: ESHandleBase(std::move(iWhyFailed)) {}

// Free swap function
Expand Down
5 changes: 5 additions & 0 deletions FWCore/Framework/test/BuildFile.xml
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,11 @@
<use name="FWCore/Framework"/>
</bin>

<bin file="test_catch2_main.cc,test_catch2_ESHandle.cc" name="TestFWCoreFrameworkESHandle">
<use name="catch2"/>
<use name="FWCore/Framework"/>
</bin>

<test name="testFWCoreFrameworkNonEventOrdering" command="test_non_event_ordering.sh"/>
<test name="testFWCoreFramework1ThreadESPrefetch" command="run_test_1_thread_es_prefetching.sh"/>
<test name="testFWCoreFrameworkModuleDeletion" command="run_module_delete_tests.sh"/>
Expand Down
221 changes: 221 additions & 0 deletions FWCore/Framework/test/test_catch2_ESHandle.cc
Original file line number Diff line number Diff line change
@@ -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<int> 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<int> 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<int> 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<int> handle(std::make_shared<TestExceptionFactory>());
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<TestExceptionFactory>();
edm::ESHandle<int> 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<TestExceptionFactory>();
edm::ESHandle<int> handleA(factory);
edm::ESHandle<int> 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<int> const handleA(&valueA, &descA);

SECTION("Constructor") {
edm::ESHandle<int> handleB(handleA);
REQUIRE(handleA.isValid());
REQUIRE(*handleA == valueA);
REQUIRE(handleB.isValid());
REQUIRE(*handleB == valueA);
}

SECTION("Assignment") {
edm::ESHandle<int> 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<int> const handleA(std::make_shared<TestExceptionFactory>());

SECTION("Constructor") {
edm::ESHandle<int> 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<int> 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<int> handleA(&valueA, &descA);

SECTION("Constructor") {
edm::ESHandle<int> handleB(std::move(handleA));
REQUIRE(handleB.isValid());
REQUIRE(*handleB == valueA);
}

SECTION("Assignment") {
edm::ESHandle<int> handleB;
REQUIRE(not handleB.isValid());

handleB = std::move(handleA);
REQUIRE(handleB.isValid());
REQUIRE(*handleB == valueA);
}
}

SECTION("From invalid ESHandle") {
edm::ESHandle<int> handleA(std::make_shared<TestExceptionFactory>());

SECTION("Constructor") {
edm::ESHandle<int> 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<int> 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<int> handleA(&valueA, &descA);

SECTION("With value") {
int const valueB = 3;
edm::ESHandle<int> 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<TestExceptionFactory>();
edm::ESHandle<int> 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);
}
}
}