|
| 1 | +#include <cassert> |
| 2 | +#include <memory> |
| 3 | +#include <stdexcept> |
| 4 | +#include <string> |
| 5 | +#include <vector> |
| 6 | + |
| 7 | +#include "DataFormats/Common/interface/WrapperBase.h" |
| 8 | +#include "DataFormats/TestObjects/interface/Thing.h" |
| 9 | +#include "DataFormats/TestObjects/interface/ThingWithDoNotSort.h" |
| 10 | +#include "DataFormats/TestObjects/interface/ThingWithPostInsert.h" |
| 11 | +#include "FWCore/Framework/interface/Event.h" |
| 12 | +#include "FWCore/Framework/interface/WrapperBaseOrphanHandle.h" |
| 13 | +#include "FWCore/Framework/interface/global/EDProducer.h" |
| 14 | +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" |
| 15 | +#include "FWCore/ParameterSet/interface/ParameterSet.h" |
| 16 | +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" |
| 17 | +#include "FWCore/Utilities/interface/EDPutToken.h" |
| 18 | + |
| 19 | +// FIXME for do_post_insert_if_available, remove when no longer needed |
| 20 | +#include "FWCore/Framework/interface/PrincipalGetAdapter.h" |
| 21 | + |
| 22 | +namespace edmtest { |
| 23 | + |
| 24 | + class WrapperBaseProducer : public edm::global::EDProducer<> { |
| 25 | + public: |
| 26 | + explicit WrapperBaseProducer(edm::ParameterSet const& ps); |
| 27 | + |
| 28 | + void produce(edm::StreamID sid, edm::Event& event, edm::EventSetup const& es) const override; |
| 29 | + |
| 30 | + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); |
| 31 | + |
| 32 | + private: |
| 33 | + edm::EDPutToken intToken_; |
| 34 | + edm::EDPutToken floatToken_; |
| 35 | + edm::EDPutToken stringToken_; |
| 36 | + edm::EDPutToken vectorToken_; |
| 37 | + edm::EDPutToken thingToken_; |
| 38 | + edm::EDPutToken thingWithPostInsertToken_; |
| 39 | + edm::EDPutToken thingWithDoNotSortToken_; |
| 40 | + edm::EDPutToken badToken_; |
| 41 | + }; |
| 42 | + |
| 43 | + template <typename T> |
| 44 | + static T& unwrap_as(edm::WrapperBase& wrapper) { |
| 45 | + // throws std::bad_cast on conversion error |
| 46 | + edm::Wrapper<T>& w = dynamic_cast<edm::Wrapper<T>&>(wrapper); |
| 47 | + |
| 48 | + // throws an execption if the wrapper is empty |
| 49 | + if (w.product() == nullptr) { |
| 50 | + throw cms::Exception("LogicError") << "Empty or invalid wrapper"; |
| 51 | + } |
| 52 | + |
| 53 | + // return the content of the wrapper |
| 54 | + return w.bareProduct(); |
| 55 | + } |
| 56 | + |
| 57 | + template <typename T> |
| 58 | + static T const& unwrap_as(edm::WrapperBase const& wrapper) { |
| 59 | + // throws std::bad_cast on conversion error |
| 60 | + edm::Wrapper<T> const& w = dynamic_cast<edm::Wrapper<T> const&>(wrapper); |
| 61 | + |
| 62 | + // throws an execption if the wrapper is empty |
| 63 | + if (w.product() == nullptr) { |
| 64 | + throw cms::Exception("LogicError") << "Empty or invalid wrapper"; |
| 65 | + } |
| 66 | + |
| 67 | + // return the content of the wrapper |
| 68 | + return *w.product(); |
| 69 | + } |
| 70 | + |
| 71 | + WrapperBaseProducer::WrapperBaseProducer(edm::ParameterSet const& iConfig) |
| 72 | + : intToken_(produces(edm::TypeID(typeid(int)))), |
| 73 | + floatToken_(produces(edm::TypeID(typeid(float)))), |
| 74 | + stringToken_(produces(edm::TypeID(typeid(std::string)))), |
| 75 | + vectorToken_(produces(edm::TypeID(typeid(std::vector<double>)))), |
| 76 | + thingToken_(produces(edm::TypeID(typeid(Thing)))), |
| 77 | + thingWithPostInsertToken_(produces(edm::TypeID(typeid(ThingWithPostInsert)))), |
| 78 | + thingWithDoNotSortToken_(produces(edm::TypeID(typeid(ThingWithDoNotSort)))), |
| 79 | + badToken_(produces(edm::TypeID(typeid(int)), "bad")) {} |
| 80 | + |
| 81 | + void WrapperBaseProducer::produce(edm::StreamID sid, edm::Event& event, edm::EventSetup const& es) const { |
| 82 | + { |
| 83 | + // Check that an int can be put into the event via a WrapperBase. |
| 84 | + int value = 42; |
| 85 | + // Copy the value into the wrapper |
| 86 | + std::unique_ptr<edm::WrapperBase> product( |
| 87 | + std::make_unique<edm::Wrapper<int>>(edm::WrapperBase::Emplace{}, value)); |
| 88 | + // FIXME Wrapper should call post_insert (if available), but that is not implemented yet |
| 89 | + edm::detail::do_post_insert_if_available(unwrap_as<int>(*product)); |
| 90 | + assert(unwrap_as<int>(*product) == value); |
| 91 | + // Move the wrapper into the event |
| 92 | + auto handle = event.put(intToken_, std::move(product)); |
| 93 | + assert(not product); |
| 94 | + assert(handle.isValid()); |
| 95 | + assert(unwrap_as<int>(*handle) == value); |
| 96 | + } |
| 97 | + |
| 98 | + { |
| 99 | + // Check that a float can be put into the event via a WrapperBase. |
| 100 | + float value = 3.14159f; |
| 101 | + // Copy the value into the wrapper |
| 102 | + std::unique_ptr<edm::WrapperBase> product(new edm::Wrapper<float>(edm::WrapperBase::Emplace{}, value)); |
| 103 | + // FIXME Wrapper should call post_insert (if available), but that is not implemented yet |
| 104 | + edm::detail::do_post_insert_if_available(unwrap_as<float>(*product)); |
| 105 | + assert(unwrap_as<float>(*product) == value); |
| 106 | + // Move the wrapper into the event |
| 107 | + auto handle = event.put(floatToken_, std::move(product)); |
| 108 | + assert(not product); |
| 109 | + assert(handle.isValid()); |
| 110 | + assert(unwrap_as<float>(*handle) == value); |
| 111 | + } |
| 112 | + |
| 113 | + { |
| 114 | + // Check that a string can be put into the event via a WrapperBase. |
| 115 | + // With small string optimisation, the underlying buffer should be inside the string object itself. |
| 116 | + std::string value = "42"; |
| 117 | + // Copy the value into the wrapper |
| 118 | + std::unique_ptr<edm::WrapperBase> product(new edm::Wrapper<std::string>(edm::WrapperBase::Emplace{}, value)); |
| 119 | + // FIXME Wrapper should call post_insert (if available), but that is not implemented yet |
| 120 | + edm::detail::do_post_insert_if_available(unwrap_as<std::string>(*product)); |
| 121 | + assert(unwrap_as<std::string>(*product) == value); |
| 122 | + // Move the wrapper into the event |
| 123 | + auto handle = event.put(stringToken_, std::move(product)); |
| 124 | + assert(not product); |
| 125 | + assert(handle.isValid()); |
| 126 | + assert(unwrap_as<std::string>(*handle) == value); |
| 127 | + } |
| 128 | + |
| 129 | + { |
| 130 | + // Check that a vector can be put into the event via a WrapperBase. |
| 131 | + // The underlying buffer is outside the vector object itself. |
| 132 | + using Vector = std::vector<double>; |
| 133 | + Vector value = {1., 1., 2., 3., 5., 8., 11., 19., 30.}; |
| 134 | + // Copy the value into the wrapper |
| 135 | + std::unique_ptr<edm::WrapperBase> product(new edm::Wrapper<Vector>(edm::WrapperBase::Emplace{}, value)); |
| 136 | + // FIXME Wrapper should call post_insert (if available), but that is not implemented yet |
| 137 | + edm::detail::do_post_insert_if_available(unwrap_as<Vector>(*product)); |
| 138 | + assert(unwrap_as<Vector>(*product) == value); |
| 139 | + // Move the wrapper into the event |
| 140 | + auto handle = event.put(vectorToken_, std::move(product)); |
| 141 | + assert(not product); |
| 142 | + assert(handle.isValid()); |
| 143 | + assert(unwrap_as<Vector>(*handle) == value); |
| 144 | + } |
| 145 | + |
| 146 | + { |
| 147 | + // Check that a Thing can be put into the event via a WrapperBase. |
| 148 | + cms_int32_t value = 99; |
| 149 | + // Copy the value into the wrapper |
| 150 | + std::unique_ptr<edm::WrapperBase> product(new edm::Wrapper<Thing>(edm::WrapperBase::Emplace{}, value)); |
| 151 | + // FIXME Wrapper should call post_insert (if available), but that is not implemented yet |
| 152 | + edm::detail::do_post_insert_if_available(unwrap_as<Thing>(*product)); |
| 153 | + assert(unwrap_as<Thing>(*product).a == value); |
| 154 | + // Move the wrapper into the event |
| 155 | + auto handle = event.put(thingToken_, std::move(product)); |
| 156 | + assert(not product); |
| 157 | + assert(handle.isValid()); |
| 158 | + assert(unwrap_as<Thing>(*handle).a == value); |
| 159 | + } |
| 160 | + |
| 161 | + { |
| 162 | + // Check that a ThingWithPostInsert can be put into the event via a WrapperBase, |
| 163 | + // and that ThingWithPostInsert::post_insert() is called by Wrapper. |
| 164 | + int32_t value = 2147483647; |
| 165 | + // Copy the value into the wrapper |
| 166 | + std::unique_ptr<edm::WrapperBase> product( |
| 167 | + new edm::Wrapper<ThingWithPostInsert>(edm::WrapperBase::Emplace{}, value)); |
| 168 | + // FIXME Wrapper should call post_insert (if available), but that is not implemented yet |
| 169 | + assert(not unwrap_as<ThingWithPostInsert>(*product).valid()); |
| 170 | + edm::detail::do_post_insert_if_available(unwrap_as<ThingWithPostInsert>(*product)); |
| 171 | + // end-of-FIXME |
| 172 | + assert(unwrap_as<ThingWithPostInsert>(*product).value() == value); |
| 173 | + assert(unwrap_as<ThingWithPostInsert>(*product).valid()); |
| 174 | + // Move the wrapper into the event |
| 175 | + auto handle = event.put(thingWithPostInsertToken_, std::move(product)); |
| 176 | + assert(not product); |
| 177 | + assert(handle.isValid()); |
| 178 | + assert(unwrap_as<ThingWithPostInsert>(*handle).value() == value); |
| 179 | + assert(unwrap_as<ThingWithPostInsert>(*handle).valid()); |
| 180 | + } |
| 181 | + |
| 182 | + { |
| 183 | + // Check that a ThingWithDoNotSort can be put into the event via a WrapperBase, |
| 184 | + // and that ThingWithDoNotSort::post_insert() is *not* called by Wrapper. |
| 185 | + int32_t value = 2147483647; |
| 186 | + // Copy the value into the wrapper |
| 187 | + std::unique_ptr<edm::WrapperBase> product( |
| 188 | + new edm::Wrapper<ThingWithDoNotSort>(edm::WrapperBase::Emplace{}, value)); |
| 189 | + // FIXME Wrapper should call post_insert (if available), but that is not implemented yet |
| 190 | + edm::detail::do_post_insert_if_available(unwrap_as<ThingWithDoNotSort>(*product)); |
| 191 | + assert(unwrap_as<ThingWithDoNotSort>(*product).value() == value); |
| 192 | + // Move the wrapper into the event |
| 193 | + auto handle = event.put(thingWithDoNotSortToken_, std::move(product)); |
| 194 | + assert(not product); |
| 195 | + assert(handle.isValid()); |
| 196 | + assert(unwrap_as<ThingWithDoNotSort>(*handle).value() == value); |
| 197 | + } |
| 198 | + |
| 199 | + { |
| 200 | + // Check that mismatches in the type of the token and of the underlying object are caught |
| 201 | + float value = 3.14159f; |
| 202 | + // Copy the value into the wrapper |
| 203 | + std::unique_ptr<edm::WrapperBase> product(new edm::Wrapper<float>(edm::WrapperBase::Emplace{}, value)); |
| 204 | + // FIXME Wrapper should call post_insert (if available), but that is not implemented yet |
| 205 | + edm::detail::do_post_insert_if_available(unwrap_as<float>(*product)); |
| 206 | + assert(unwrap_as<float>(*product) == value); |
| 207 | + bool failed = false; |
| 208 | + try { |
| 209 | + event.put(badToken_, std::move(product)); |
| 210 | + } catch (edm::Exception const& e) { |
| 211 | + assert(e.categoryCode() == edm::errors::LogicError); |
| 212 | + failed = true; |
| 213 | + } |
| 214 | + assert(failed); |
| 215 | + } |
| 216 | + } |
| 217 | + |
| 218 | + void WrapperBaseProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { |
| 219 | + edm::ParameterSetDescription desc; |
| 220 | + descriptions.addWithDefaultLabel(desc); |
| 221 | + } |
| 222 | + |
| 223 | +} // namespace edmtest |
| 224 | + |
| 225 | +#include "FWCore/Framework/interface/MakerMacros.h" |
| 226 | +using edmtest::WrapperBaseProducer; |
| 227 | +DEFINE_FWK_MODULE(WrapperBaseProducer); |
0 commit comments