add PVRequestMapper

utility to having pvRequest .field mangling

Warn if requesting some non-existant fields.
Error if no requested fields exist.

PVRequestMapper mode enum to select between
two "styles" of interpretation.
This commit is contained in:
Michael Davidsaver
2018-07-30 14:38:13 -07:00
parent 64158376f5
commit 342b1bc8ef
4 changed files with 860 additions and 1 deletions

View File

@@ -434,14 +434,380 @@ static void testMask()
.set(V->getSubField("A")->getFieldOffset()));
}
static
void testMapper(PVRequestMapper::mode_t mode)
{
testDiag("=== %s mode==%d", CURRENT_FUNCTION, (int)mode);
{
testDiag("Map full structure");
PVStructurePtr base(getPVDataCreate()->createPVStructure(maskingType));
PVRequestMapper mapper(*base, *createRequest(""), mode);
testEqual(mapper.requested(), maskingType);
testEqual(mapper.requestedMask(), BitSet().set(0)
.set(base->getSubFieldT("A")->getFieldOffset())
.set(base->getSubFieldT("B")->getFieldOffset())
.set(base->getSubFieldT("C")->getFieldOffset())
.set(base->getSubFieldT("C.D")->getFieldOffset())
.set(base->getSubFieldT("C.E")->getFieldOffset())
.set(base->getSubFieldT("C.E.F")->getFieldOffset()));
PVStructurePtr req(getPVDataCreate()->createPVStructure(mapper.requested()));
base->getSubFieldT<PVInt>("A")->put(1);
base->getSubFieldT<PVInt>("B")->put(42);
BitSet output;
mapper.copyBaseToRequested(*base, BitSet().set(0), *req, output);
testFieldEqual<PVInt>(req, "A", 1);
testFieldEqual<PVInt>(req, "B", 42);
req->getSubFieldT<PVInt>("A")->put(2);
req->getSubFieldT<PVInt>("B")->put(43);
mapper.copyBaseFromRequested(*base, output, *req, BitSet().set(0));
testFieldEqual<PVInt>(req, "A", 2);
testFieldEqual<PVInt>(req, "B", 43);
testEqual(mapper.requestedMask(), BitSet().set(0).set(1).set(2).set(3).set(4).set(5).set(6));
}
{
testDiag("Map single leaf field");
PVStructurePtr base(getPVDataCreate()->createPVStructure(maskingType));
PVRequestMapper mapper(*base, *createRequest("field(B)"), mode);
if(mode==PVRequestMapper::Slice)
testNotEqual(mapper.requested(), maskingType);
else
testEqual(mapper.requested(), maskingType);
testEqual(mapper.requestedMask(), BitSet().set(0)
.set(base->getSubFieldT("B")->getFieldOffset()));
PVStructurePtr req(getPVDataCreate()->createPVStructure(mapper.requested()));
if(mode==PVRequestMapper::Slice)
testOk1(!req->getSubField("A"));
base->getSubFieldT<PVScalar>("A")->putFrom<int32>(11);
base->getSubFieldT<PVScalar>("B")->putFrom<int32>(42);
BitSet output;
mapper.copyBaseToRequested(*base, BitSet().set(0), *req, output);
if(mode!=PVRequestMapper::Slice)
testFieldEqual<PVInt>(req, "A", 0);
testFieldEqual<PVInt>(req, "B", 42);
req->getSubFieldT<PVScalar>("B")->putFrom<int32>(43);
mapper.copyBaseFromRequested(*base, output, *req, BitSet().set(0));
testFieldEqual<PVInt>(req, "B", 43);
testEqual(mapper.requestedMask(), BitSet().set(0)
.set(base->getSubFieldT("B")->getFieldOffset()));
BitSet cmp;
mapper.maskBaseToRequested(BitSet().set(base->getSubFieldT("B")->getFieldOffset()), cmp);
testEqual(cmp, BitSet()
.set(req->getSubFieldT("B")->getFieldOffset()));
cmp.clear();
mapper.maskBaseFromRequested(cmp, BitSet()
.set(req->getSubFieldT("B")->getFieldOffset()));
testEqual(cmp, BitSet()
.set(base->getSubFieldT("B")->getFieldOffset()));
}
{
testDiag("Map two sub-fields");
PVStructurePtr base(getPVDataCreate()->createPVStructure(maskingType));
PVRequestMapper mapper(*base, *createRequest("B,C.D"), mode);
if(mode==PVRequestMapper::Slice)
testNotEqual(mapper.requested(), maskingType);
else
testEqual(mapper.requested(), maskingType);
testEqual(mapper.requestedMask(), BitSet().set(0)
.set(base->getSubFieldT("B")->getFieldOffset())
.set(base->getSubFieldT("C")->getFieldOffset())
.set(base->getSubFieldT("C.D")->getFieldOffset()));
PVStructurePtr req(getPVDataCreate()->createPVStructure(mapper.requested()));
if(mode==PVRequestMapper::Slice)
testOk1(!req->getSubField("A"));
base->getSubFieldT<PVScalar>("A")->putFrom<int32>(11);
base->getSubFieldT<PVScalar>("B")->putFrom<int32>(1);
base->getSubFieldT<PVScalar>("C.D")->putFrom<int32>(42);
BitSet output;
mapper.copyBaseToRequested(*base, BitSet().set(0), *req, output);
if(mode!=PVRequestMapper::Slice)
testFieldEqual<PVInt>(req, "A", 0);
testFieldEqual<PVInt>(req, "B", 1);
testFieldEqual<PVInt>(req, "C.D", 42);
req->getSubFieldT<PVScalar>("B")->putFrom<int32>(2);
req->getSubFieldT<PVScalar>("C.D")->putFrom<int32>(43);
mapper.copyBaseFromRequested(*base, output, *req, BitSet().set(0));
testFieldEqual<PVInt>(req, "B", 2);
testFieldEqual<PVInt>(req, "C.D", 43);
testEqual(mapper.requestedMask(), BitSet().set(0)
.set(base->getSubFieldT("B")->getFieldOffset())
.set(base->getSubFieldT("C")->getFieldOffset())
.set(base->getSubFieldT("C.D")->getFieldOffset()));
}
{
testDiag("Map entire sub-structure");
PVStructurePtr base(getPVDataCreate()->createPVStructure(maskingType));
PVRequestMapper mapper(*base, *createRequest("field(C.E)"), mode);
if(mode==PVRequestMapper::Slice)
testNotEqual(mapper.requested(), maskingType);
else
testEqual(mapper.requested(), maskingType);
testEqual(mapper.requestedMask(), BitSet().set(0)
.set(base->getSubFieldT("C")->getFieldOffset())
.set(base->getSubFieldT("C.E")->getFieldOffset())
.set(base->getSubFieldT("C.E.F")->getFieldOffset()));
PVStructurePtr req(getPVDataCreate()->createPVStructure(mapper.requested()));
if(mode==PVRequestMapper::Slice)
testOk1(!req->getSubField("A"));
base->getSubFieldT<PVScalar>("A")->putFrom<int32>(11);
base->getSubFieldT<PVScalar>("C.E.F")->putFrom<int32>(42);
BitSet output;
mapper.copyBaseToRequested(*base, BitSet().set(0), *req, output);
if(mode!=PVRequestMapper::Slice)
testFieldEqual<PVInt>(req, "A", 0);
testFieldEqual<PVInt>(req, "C.E.F", 42);
req->getSubFieldT<PVScalar>("C.E.F")->putFrom<int32>(43);
mapper.copyBaseFromRequested(*base, output, *req, BitSet().set(0));
testFieldEqual<PVInt>(req, "C.E.F", 43);
testEqual(mapper.requestedMask(), BitSet().set(0)
.set(base->getSubFieldT("C")->getFieldOffset())
.set(base->getSubFieldT("C.E")->getFieldOffset())
.set(base->getSubFieldT("C.E.F")->getFieldOffset()));
BitSet cmp;
mapper.maskBaseToRequested(BitSet()
.set(base->getSubFieldT("C")->getFieldOffset()), cmp);
testEqual(cmp, BitSet()
.set(req->getSubFieldT("C")->getFieldOffset())
.set(req->getSubFieldT("C.E")->getFieldOffset())
.set(req->getSubFieldT("C.E.F")->getFieldOffset()));
cmp.clear();
mapper.maskBaseFromRequested(cmp, BitSet()
.set(req->getSubFieldT("C")->getFieldOffset()));
testEqual(cmp, BitSet()
.set(base->getSubFieldT("C")->getFieldOffset())
.set(base->getSubFieldT("C.E")->getFieldOffset())
.set(base->getSubFieldT("C.E.F")->getFieldOffset()));
}
}
struct MapperMask {
PVStructurePtr base, req;
BitSet bmask, rmask;
PVRequestMapper mapper;
MapperMask(PVRequestMapper::mode_t mode) {
base = getPVDataCreate()->createPVStructure(maskingType);
mapper.compute(*base, *createRequest("field(B,C.E)"), mode);
req = getPVDataCreate()->createPVStructure(mapper.requested());
reset();
}
void reset() {
base->getSubFieldT<PVScalar>("B")->putFrom<int32>(1);
base->getSubFieldT<PVScalar>("C.E.F")->putFrom<int32>(3);
req->getSubFieldT<PVScalar>("B")->putFrom<int32>(11);
req->getSubFieldT<PVScalar>("C.E.F")->putFrom<int32>(13);
}
void check(int32 bB, int32 bCEF, int32 rB, int32 rCEF) {
testFieldEqual<PVInt>(base, "B", bB);
testFieldEqual<PVInt>(base, "C.E.F", bCEF);
testFieldEqual<PVInt>(req, "B", rB);
testFieldEqual<PVInt>(req, "C.E.F", rCEF);
}
void testEmptyMaskB2R() {
mapper.copyBaseToRequested(*base, bmask, *req, rmask);
check(1, 3, 11, 13);
testEqual(bmask, BitSet());
testEqual(rmask, BitSet());
}
void testEmptyMaskR2B() {
mapper.copyBaseFromRequested(*base, bmask, *req, rmask);
check(1, 3, 11, 13);
testEqual(bmask, BitSet());
testEqual(rmask, BitSet());
}
void testAllMaskB2R() {
bmask.set(0);
mapper.copyBaseToRequested(*base, bmask, *req, rmask);
check(1, 3, 1, 3);
testEqual(rmask, BitSet()
.set(0)
.set(req->getSubFieldT("B")->getFieldOffset())
.set(req->getSubFieldT("C")->getFieldOffset())
.set(req->getSubFieldT("C.E")->getFieldOffset())
.set(req->getSubFieldT("C.E.F")->getFieldOffset()));
}
void testAllMaskR2B() {
rmask.set(0);
mapper.copyBaseFromRequested(*base, bmask, *req, rmask);
check(11, 13, 11, 13);
testEqual(bmask, BitSet()
.set(0)
.set(base->getSubFieldT("B")->getFieldOffset())
.set(base->getSubFieldT("C")->getFieldOffset())
.set(base->getSubFieldT("C.E")->getFieldOffset())
.set(base->getSubFieldT("C.E.F")->getFieldOffset()));
}
void testMaskOneB2R() {
bmask.set(base->getSubFieldT("B")->getFieldOffset());
mapper.copyBaseToRequested(*base, bmask, *req, rmask);
check(1, 3, 1, 13);
testEqual(rmask, BitSet()
.set(req->getSubFieldT("B")->getFieldOffset()));
}
void testMaskOneR2B() {
rmask.set(req->getSubFieldT("B")->getFieldOffset());
mapper.copyBaseFromRequested(*base, bmask, *req, rmask);
check(11, 3, 11, 13);
testEqual(bmask, BitSet()
.set(base->getSubFieldT("B")->getFieldOffset()));
}
void testMaskOtherB2R() {
bmask.set(base->getSubFieldT("C.E.F")->getFieldOffset());
mapper.copyBaseToRequested(*base, bmask, *req, rmask);
check(1, 3, 11, 3);
testEqual(rmask, BitSet()
.set(req->getSubFieldT("C.E.F")->getFieldOffset()));
}
void testMaskOtherR2B() {
rmask.set(req->getSubFieldT("C.E.F")->getFieldOffset());
mapper.copyBaseFromRequested(*base, bmask, *req, rmask);
check(1, 13, 11, 13);
testEqual(bmask, BitSet()
.set(base->getSubFieldT("C.E.F")->getFieldOffset()));
}
void testMaskSub1B2R() {
bmask.set(base->getSubFieldT("C.E")->getFieldOffset());
mapper.copyBaseToRequested(*base, bmask, *req, rmask);
check(1, 3, 11, 3);
testEqual(rmask, BitSet()
.set(req->getSubFieldT("C.E")->getFieldOffset())
.set(req->getSubFieldT("C.E.F")->getFieldOffset()));
}
void testMaskSub1R2B() {
rmask.set(req->getSubFieldT("C.E")->getFieldOffset());
mapper.copyBaseFromRequested(*base, bmask, *req, rmask);
check(1, 13, 11, 13);
testEqual(bmask, BitSet()
.set(base->getSubFieldT("C.E")->getFieldOffset())
.set(base->getSubFieldT("C.E.F")->getFieldOffset()));
}
void testMaskSub2B2R() {
bmask.set(base->getSubFieldT("C")->getFieldOffset());
mapper.copyBaseToRequested(*base, bmask, *req, rmask);
check(1, 3, 11, 3);
testEqual(rmask, BitSet()
.set(req->getSubFieldT("C")->getFieldOffset())
.set(req->getSubFieldT("C.E")->getFieldOffset())
.set(req->getSubFieldT("C.E.F")->getFieldOffset()));
}
void testMaskSub2R2B() {
rmask.set(req->getSubFieldT("C")->getFieldOffset());
mapper.copyBaseFromRequested(*base, bmask, *req, rmask);
check(1, 13, 11, 13);
testEqual(bmask, BitSet()
.set(base->getSubFieldT("C")->getFieldOffset())
.set(base->getSubFieldT("C.E")->getFieldOffset())
.set(base->getSubFieldT("C.E.F")->getFieldOffset()));
}
};
void testMaskWarn()
{
PVStructurePtr base(getPVDataCreate()->createPVStructure(maskingType));
PVRequestMapper mapper(*base, *createRequest("field(B,invalid)"), PVRequestMapper::Slice);
testEqual(mapper.warnings(), "No field 'invalid' ");
}
void testMaskErr()
{
PVStructurePtr base(getPVDataCreate()->createPVStructure(maskingType));
testThrows(std::runtime_error, PVRequestMapper mapper(*base, *createRequest("field(invalid)"), PVRequestMapper::Slice));
}
} // namespace
MAIN(testCreateRequest)
{
testPlan(141);
testPlan(329);
testCreateRequestInternal();
testBadRequest();
testMask();
testMapper(PVRequestMapper::Slice);
testMapper(PVRequestMapper::Mask);
#undef TEST_METHOD
#define TEST_METHOD(KLASS, METHOD) \
{ \
testDiag("------- %s::%s Mask --------", #KLASS, #METHOD); \
{ KLASS inst(PVRequestMapper::Mask); inst.METHOD(); } \
testDiag("------- %s::%s Slice --------", #KLASS, #METHOD); \
{ KLASS inst(PVRequestMapper::Slice); inst.METHOD(); } \
}
TEST_METHOD(MapperMask, testEmptyMaskB2R);
TEST_METHOD(MapperMask, testEmptyMaskR2B);
TEST_METHOD(MapperMask, testAllMaskB2R);
TEST_METHOD(MapperMask, testAllMaskR2B);
TEST_METHOD(MapperMask, testMaskOneB2R);
TEST_METHOD(MapperMask, testMaskOneR2B);
TEST_METHOD(MapperMask, testMaskOtherB2R);
TEST_METHOD(MapperMask, testMaskOtherR2B);
TEST_METHOD(MapperMask, testMaskSub1B2R);
TEST_METHOD(MapperMask, testMaskSub1R2B);
TEST_METHOD(MapperMask, testMaskSub2B2R);
TEST_METHOD(MapperMask, testMaskSub2R2B);
testMaskWarn();
testMaskErr();
return testDone();
}