Skip to content

Commit 85c6480

Browse files
fwyzardmakortel
andcommitted
Implement integration tests for WrapperBase specialisations
Co-authored-by: Matti Kortelainen <[email protected]>
1 parent 49212d7 commit 85c6480

File tree

4 files changed

+276
-0
lines changed

4 files changed

+276
-0
lines changed

FWCore/Integration/plugins/BuildFile.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@
3333
<use name="DataFormats/TestObjects"/>
3434
</library>
3535

36+
<library file="WrapperBaseProducer.cc" name="FWCoreIntegrationWrapperBase">
37+
<flags EDM_PLUGIN="1"/>
38+
<use name="DataFormats/TestObjects"/>
39+
<use name="FWCore/Framework"/>
40+
<use name="FWCore/ParameterSet"/>
41+
<use name="FWCore/Reflection"/>
42+
<use name="FWCore/Utilities"/>
43+
</library>
44+
3645
<library file="HistProducer.cc" name="TestHistProducer">
3746
<flags EDM_PLUGIN="1"/>
3847
<use name="FWCore/Framework"/>
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
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);

FWCore/Integration/test/BuildFile.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
<test name="CatchCmsExceptiontest" command="CatchCmsExceptiontest.sh"/>
3232
<test name="TestStdProducts" command="cmsRun ${LOCALTOP}/src/FWCore/Integration/test/testStdProducts_cfg.py"/>
3333
<test name="TestPostInsertProducer" command="cmsRun ${LOCALTOP}/src/FWCore/Integration/test/testPostInsertProducer_cfg.py"/>
34+
<test name="TestWrapperBaseProducer" command="cmsRun ${LOCALTOP}/src/FWCore/Integration/test/testWrapperBaseProducer_cfg.py"/>
3435

3536
<bin file="ProcessConfiguration_t.cpp,ProcessHistory_t.cpp" name="TestIntegrationDataFormatsProvenance">
3637
<use name="FWCore/ParameterSet"/>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import FWCore.ParameterSet.Config as cms
2+
3+
process = cms.Process("TEST")
4+
5+
process.source = cms.Source("EmptySource")
6+
7+
process.maxEvents = cms.untracked.PSet(
8+
input = cms.untracked.int32(10)
9+
)
10+
11+
process.producer = cms.EDProducer("WrapperBaseProducer")
12+
13+
process.validateInt = cms.EDAnalyzer("edmtest::GlobalIntAnalyzer",
14+
source = cms.InputTag("producer"),
15+
expected = cms.int32(42) # hard-coded in WrapperBaseProducer
16+
)
17+
18+
process.validateFloat = cms.EDAnalyzer("edmtest::GlobalFloatAnalyzer",
19+
source = cms.InputTag("producer"),
20+
expected = cms.double(3.14159) # hard-coded in WrapperBaseProducer
21+
)
22+
23+
process.validateString = cms.EDAnalyzer("edmtest::GlobalStringAnalyzer",
24+
source = cms.InputTag("producer"),
25+
expected = cms.string("42") # hard-coded in WrapperBaseProducer
26+
)
27+
28+
process.validateVector = cms.EDAnalyzer("edmtest::GlobalVectorAnalyzer",
29+
source = cms.InputTag("producer"),
30+
expected = cms.vdouble(1., 1., 2., 3., 5., 8., 11., 19., 30.) # hard-coded in WrapperBaseProducer
31+
)
32+
33+
process.path = cms.Path(
34+
process.producer +
35+
process.validateInt +
36+
process.validateFloat +
37+
process.validateString +
38+
process.validateVector
39+
)

0 commit comments

Comments
 (0)