741 lines
23 KiB
C++
741 lines
23 KiB
C++
/**
|
|
* Copyright - See the COPYRIGHT that is included with this distribution.
|
|
* EPICS pvData is distributed subject to a Software License Agreement found
|
|
* in file LICENSE that is included with this distribution.
|
|
*/
|
|
/*
|
|
* testSerialization.cpp
|
|
*
|
|
* Created on: Oct 25, 2010
|
|
* Author: Miha Vitorovic
|
|
*/
|
|
|
|
#ifdef _WIN32
|
|
#define NOMINMAX
|
|
#endif
|
|
|
|
#include <iostream>
|
|
#include <fstream>
|
|
|
|
#include <epicsUnitTest.h>
|
|
#include <testMain.h>
|
|
#include <dbDefs.h> // for NELEMENTS
|
|
|
|
#include <epicsExit.h>
|
|
#include <pv/pvIntrospect.h>
|
|
#include <pv/pvData.h>
|
|
#include <pv/serialize.h>
|
|
#include <pv/noDefaultMethods.h>
|
|
#include <pv/byteBuffer.h>
|
|
#include <pv/convert.h>
|
|
|
|
#include <pv/standardField.h>
|
|
|
|
#include <limits>
|
|
|
|
#define BYTE_MAX_VALUE std::numeric_limits<int8>::max()
|
|
#define BYTE_MIN_VALUE std::numeric_limits<int8>::min()
|
|
#define UBYTE_MAX_VALUE std::numeric_limits<uint8>::max()
|
|
#define SHORT_MAX_VALUE std::numeric_limits<int16>::max()
|
|
#define SHORT_MIN_VALUE std::numeric_limits<int16>::min()
|
|
#define USHORT_MAX_VALUE std::numeric_limits<uint16>::max()
|
|
#define INT_MAX_VALUE std::numeric_limits<int32>::max()
|
|
#define INT_MIN_VALUE std::numeric_limits<int32>::min()
|
|
#define UINT_MAX_VALUE std::numeric_limits<uint32>::max()
|
|
#define LONG_MAX_VALUE std::numeric_limits<int64>::max()
|
|
#define LONG_MIN_VALUE std::numeric_limits<int64>::min()
|
|
#define ULONG_MAX_VALUE std::numeric_limits<uint64>::max()
|
|
#define FLOAT_MAX_VALUE std::numeric_limits<float>::max()
|
|
#define FLOAT_MIN_VALUE std::numeric_limits<float>::min()
|
|
#define DOUBLE_MAX_VALUE std::numeric_limits<double>::max()
|
|
#define DOUBLE_MIN_VALUE std::numeric_limits<double>::min()
|
|
|
|
using namespace epics::pvData;
|
|
|
|
namespace {
|
|
|
|
static SerializableControl* flusher;
|
|
static DeserializableControl* control;
|
|
static ByteBuffer* buffer;
|
|
|
|
|
|
class SerializableControlImpl : public SerializableControl,
|
|
public NoDefaultMethods {
|
|
public:
|
|
virtual void flushSerializeBuffer() {
|
|
}
|
|
|
|
virtual void ensureBuffer(std::size_t /*size*/) {
|
|
}
|
|
|
|
virtual void alignBuffer(std::size_t alignment) {
|
|
buffer->align(alignment);
|
|
}
|
|
|
|
virtual bool directSerialize(ByteBuffer* /*existingBuffer*/, const char* /*toSerialize*/,
|
|
std::size_t /*elementCount*/, std::size_t /*elementSize*/)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
virtual void cachedSerialize(std::tr1::shared_ptr<const Field> const & field, ByteBuffer* buffer)
|
|
{
|
|
field->serialize(buffer, this);
|
|
}
|
|
|
|
SerializableControlImpl() {
|
|
}
|
|
|
|
virtual ~SerializableControlImpl() {
|
|
}
|
|
};
|
|
|
|
class DeserializableControlImpl : public DeserializableControl,
|
|
public NoDefaultMethods {
|
|
public:
|
|
virtual void ensureData(size_t /*size*/) {
|
|
}
|
|
|
|
virtual void alignData(size_t alignment) {
|
|
buffer->align(alignment);
|
|
}
|
|
|
|
virtual bool directDeserialize(ByteBuffer* /*existingBuffer*/, char* /*deserializeTo*/,
|
|
std::size_t /*elementCount*/, std::size_t /*elementSize*/)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
virtual std::tr1::shared_ptr<const Field> cachedDeserialize(ByteBuffer* buffer)
|
|
{
|
|
return getFieldCreate()->deserialize(buffer, this);
|
|
}
|
|
|
|
DeserializableControlImpl() {
|
|
}
|
|
|
|
virtual ~DeserializableControlImpl() {
|
|
}
|
|
};
|
|
|
|
void serializationTest(PVFieldPtr const & field) {
|
|
buffer->clear();
|
|
|
|
// serialize
|
|
field->serialize(buffer, flusher);
|
|
|
|
buffer->flip();
|
|
|
|
// create new instance and deserialize
|
|
PVFieldPtr deserializedField = getPVDataCreate()->createPVField(field->getField());
|
|
deserializedField->deserialize(buffer, control);
|
|
|
|
// must equal
|
|
if(*field==*deserializedField)
|
|
testPass("Serialization round trip OK");
|
|
else {
|
|
testFail("Serialization round trip did not match!");
|
|
std::string buf;
|
|
field->toString(&buf);
|
|
testDiag("Expected: %s", buf.c_str());
|
|
buf.clear();
|
|
deserializedField->toString(&buf);
|
|
testDiag("Found: %s", buf.c_str());
|
|
}
|
|
}
|
|
|
|
void testEquals() {
|
|
testDiag("Testing equals..."); // and non-initialized
|
|
PVDataCreatePtr factory = getPVDataCreate();
|
|
testOk1(factory.get()!=NULL);
|
|
|
|
// be sure all is covered
|
|
for (int i = pvBoolean; i < pvString; i++)
|
|
{
|
|
ScalarType scalarType = static_cast<ScalarType>(i);
|
|
|
|
PVScalarPtr scalar1 = factory->createPVScalar(scalarType);
|
|
PVScalarPtr scalar2 = factory->createPVScalar(scalarType);
|
|
testOk1((*scalar1)==(*scalar2));
|
|
|
|
PVScalarArrayPtr array1 = factory->createPVScalarArray(scalarType);
|
|
PVScalarArrayPtr array2 = factory->createPVScalarArray(scalarType);
|
|
testOk1((*array1)==(*array2));
|
|
}
|
|
|
|
// and a structure
|
|
PVStructurePtr structure1 = factory->createPVStructure(getStandardField()->timeStamp());
|
|
PVStructurePtr structure2 = factory->createPVStructure(getStandardField()->timeStamp());
|
|
testOk1((*structure1)==(*structure2));
|
|
|
|
// and a structure array
|
|
PVStructureArrayPtr structureArray1 = factory->createPVStructureArray(getFieldCreate()->createStructureArray(structure1->getStructure()));
|
|
PVStructureArrayPtr structureArray2 = factory->createPVStructureArray(getFieldCreate()->createStructureArray(structure2->getStructure()));
|
|
testOk1((*structureArray1)==(*structureArray2));
|
|
|
|
// variant union
|
|
PVUnionPtr variantUnion1 = factory->createPVVariantUnion();
|
|
PVUnionPtr variantUnion2 = factory->createPVVariantUnion();
|
|
testOk1((*variantUnion1)==(*variantUnion2));
|
|
|
|
variantUnion1->set(structure1);
|
|
variantUnion2->set(structure1);
|
|
testOk1((*variantUnion1)==(*variantUnion2));
|
|
|
|
variantUnion2->set(structureArray1);
|
|
testOk1((*variantUnion1)!=(*variantUnion2));
|
|
|
|
// variant union array
|
|
PVUnionArrayPtr variantUnionArray1 = factory->createPVVariantUnionArray();
|
|
PVUnionArrayPtr variantUnionArray2 = factory->createPVVariantUnionArray();
|
|
testOk1((*variantUnionArray1)==(*variantUnionArray2));
|
|
|
|
// union
|
|
UnionConstPtr punion = getFieldCreate()->createFieldBuilder()->
|
|
add("double", pvDouble)->
|
|
add("double2", pvDouble)->
|
|
addNestedStructureArray("nested")->
|
|
setId("nestedId")->
|
|
add("short", pvShort)->
|
|
add("long", pvLong)->
|
|
endNested()->
|
|
addArray("intArray", pvInt)->
|
|
createUnion();
|
|
PVUnionPtr union1 = factory->createPVUnion(punion);
|
|
PVUnionPtr union2 = factory->createPVUnion(punion);
|
|
testOk1((*union1)==(*union2));
|
|
|
|
union1->select<PVDouble>("double")->put(1.2);
|
|
union2->select<PVDouble>("double")->put(1.2);
|
|
testOk1((*union1)==(*union2));
|
|
|
|
union2->select<PVDouble>("double")->put(2.2);
|
|
testOk1((*union1)!=(*union2));
|
|
|
|
union2->select<PVDouble>("double2")->put(1.2);
|
|
testOk1((*union1)!=(*union2));
|
|
|
|
union2->select("nested");
|
|
testOk1((*union1)!=(*union2));
|
|
|
|
testOk1((*union1)!=(*variantUnion2));
|
|
|
|
PVUnionArrayPtr unionArray1 = factory->createPVUnionArray(getFieldCreate()->createUnionArray(punion));
|
|
PVUnionArrayPtr unionArray2 = factory->createPVUnionArray(getFieldCreate()->createUnionArray(punion));
|
|
testOk1((*unionArray1)==(*unionArray2));
|
|
|
|
testOk1((*variantUnionArray1)!=(*unionArray2));
|
|
}
|
|
|
|
template<typename PVT>
|
|
void testScalarType()
|
|
{
|
|
typedef typename PVT::value_type value_type;
|
|
|
|
testDiag("type %s", ScalarTypeFunc::name(PVT::typeCode));
|
|
|
|
typename PVT::shared_pointer pv = std::tr1::static_pointer_cast<PVT>(getPVDataCreate()->createPVScalar(PVT::typeCode));
|
|
|
|
pv->put(0);
|
|
serializationTest(pv);
|
|
pv->put(42);
|
|
serializationTest(pv);
|
|
pv->put(std::numeric_limits<value_type>::max()-1);
|
|
serializationTest(pv);
|
|
pv->put(std::numeric_limits<value_type>::max());
|
|
serializationTest(pv);
|
|
|
|
if(std::numeric_limits<value_type>::min()!=0) {
|
|
pv->put(-42);
|
|
serializationTest(pv);
|
|
pv->put(std::numeric_limits<value_type>::min()+1);
|
|
serializationTest(pv);
|
|
pv->put(std::numeric_limits<value_type>::min());
|
|
serializationTest(pv);
|
|
}
|
|
|
|
if(std::numeric_limits<value_type>::has_infinity) {
|
|
pv->put(std::numeric_limits<value_type>::infinity());
|
|
serializationTest(pv);
|
|
}
|
|
}
|
|
|
|
void testScalar() {
|
|
testDiag("Testing scalars...");
|
|
PVDataCreatePtr factory = getPVDataCreate();
|
|
testOk1(factory.get()!=NULL);
|
|
|
|
testDiag("type %s", ScalarTypeFunc::name(pvBoolean));
|
|
PVBooleanPtr pvBoolean =
|
|
std::tr1::static_pointer_cast<PVBoolean>(factory->createPVScalar(epics::pvData::pvBoolean));
|
|
pvBoolean->put(false);
|
|
serializationTest(pvBoolean);
|
|
pvBoolean->put(true);
|
|
serializationTest(pvBoolean);
|
|
|
|
testScalarType<PVByte>();
|
|
testScalarType<PVUByte>();
|
|
testScalarType<PVShort>();
|
|
testScalarType<PVUShort>();
|
|
testScalarType<PVInt>();
|
|
testScalarType<PVUInt>();
|
|
testScalarType<PVLong>();
|
|
testScalarType<PVULong>();
|
|
testScalarType<PVFloat>();
|
|
testScalarType<PVDouble>();
|
|
|
|
|
|
testDiag("type %s", ScalarTypeFunc::name(pvString));
|
|
PVStringPtr pvString =
|
|
std::tr1::static_pointer_cast<PVString>(factory->createPVScalar(epics::pvData::pvString));
|
|
pvString->put("");
|
|
serializationTest(pvString);
|
|
pvString->put("s");
|
|
serializationTest(pvString);
|
|
pvString->put("string");
|
|
serializationTest(pvString);
|
|
pvString->put("string with spaces");
|
|
serializationTest(pvString);
|
|
pvString->put("string with spaces and special characters\f\n");
|
|
serializationTest(pvString);
|
|
|
|
// huge string test
|
|
pvString->put(String(10000, 'a'));
|
|
serializationTest(pvString);
|
|
}
|
|
|
|
template<typename PVT>
|
|
void testArrayType(const typename PVT::value_type* rdata, size_t len)
|
|
{
|
|
typename PVT::svector empty(0), data(len);
|
|
|
|
std::copy(rdata, rdata+len, data.begin());
|
|
|
|
testDiag("type %s", ScalarTypeFunc::name(PVT::typeCode));
|
|
|
|
typename PVT::shared_pointer pv = std::tr1::static_pointer_cast<PVT>(getPVDataCreate()->createPVScalarArray(PVT::typeCode));
|
|
|
|
pv->replace(freeze(empty));
|
|
serializationTest(pv);
|
|
pv->replace(freeze(data));
|
|
serializationTest(pv);
|
|
}
|
|
|
|
static const epics::pvData::boolean bdata[] = {0, 1, 0, 1, 1};
|
|
|
|
static const int8 i8data[] = { 0, 1, 2, -1, BYTE_MAX_VALUE, static_cast<int8>(BYTE_MAX_VALUE-1),
|
|
static_cast<int8>(BYTE_MIN_VALUE+1), BYTE_MIN_VALUE };
|
|
static const uint8 u8data[] = { 0, 1, 2, static_cast<uint8>(-1), UBYTE_MAX_VALUE, static_cast<uint8>(UBYTE_MAX_VALUE-1) };
|
|
|
|
static const int16 i16data[] = { 0, 1, 2, -1, SHORT_MAX_VALUE, static_cast<int16>(SHORT_MAX_VALUE-1),
|
|
static_cast<int16>(SHORT_MIN_VALUE+1), SHORT_MIN_VALUE };
|
|
static const uint16 u16data[] = { 0, 1, 2, static_cast<uint16>(-1), USHORT_MAX_VALUE, static_cast<uint16>(USHORT_MAX_VALUE-1) };
|
|
|
|
static const int32 i32data[] = { 0, 1, 2, -1, INT_MAX_VALUE, INT_MAX_VALUE-1,
|
|
INT_MIN_VALUE+1, INT_MIN_VALUE };
|
|
static const uint32 u32data[] = { 0, 1, 2, static_cast<uint32>(-1), UINT_MAX_VALUE, UINT_MAX_VALUE-1 };
|
|
|
|
static const int64 i64data[] = { 0, 1, 2, -1, LONG_MAX_VALUE, static_cast<int64>(LONG_MAX_VALUE-1),
|
|
static_cast<int64>(LONG_MIN_VALUE+1), LONG_MIN_VALUE };
|
|
static const uint64 u64data[] = { 0, 1, 2, static_cast<uint64>(-1), ULONG_MAX_VALUE, static_cast<uint64>(ULONG_MAX_VALUE-1) };
|
|
|
|
static const double ddata[] = { (double)0.0, (double)1.1, (double)2.3, (double)-1.4,
|
|
DOUBLE_MAX_VALUE, DOUBLE_MAX_VALUE-(double)123456.789,
|
|
DOUBLE_MIN_VALUE+(double)1.1, DOUBLE_MIN_VALUE };
|
|
|
|
static const float fdata[] = { (float)0.0, (float)1.1, (float)2.3, (float)-1.4,
|
|
FLOAT_MAX_VALUE, FLOAT_MAX_VALUE-(float)123456.789,
|
|
FLOAT_MIN_VALUE+(float)1.1, FLOAT_MIN_VALUE };
|
|
|
|
static const String sdata[] = {
|
|
"",
|
|
"a",
|
|
"a b",
|
|
" ",
|
|
"test",
|
|
"smile",
|
|
"this is a little longer string... maybe a little but longer... this makes test better",
|
|
String(10000, 'b')
|
|
};
|
|
|
|
void testArray() {
|
|
testDiag("Testing arrays...");
|
|
|
|
testArrayType<PVBooleanArray>(bdata, NELEMENTS(bdata));
|
|
|
|
testArrayType<PVByteArray>(i8data, NELEMENTS(i8data));
|
|
testArrayType<PVUByteArray>(u8data, NELEMENTS(u8data));
|
|
testArrayType<PVShortArray>(i16data, NELEMENTS(i16data));
|
|
testArrayType<PVUShortArray>(u16data, NELEMENTS(u16data));
|
|
testArrayType<PVIntArray>(i32data, NELEMENTS(i32data));
|
|
testArrayType<PVUIntArray>(u32data, NELEMENTS(u32data));
|
|
testArrayType<PVLongArray>(i64data, NELEMENTS(i64data));
|
|
testArrayType<PVULongArray>(u64data, NELEMENTS(u64data));
|
|
|
|
testArrayType<PVDoubleArray>(ddata, NELEMENTS(ddata));
|
|
testArrayType<PVFloatArray>(fdata, NELEMENTS(fdata));
|
|
|
|
testArrayType<PVStringArray>(sdata, NELEMENTS(sdata));
|
|
}
|
|
|
|
void testStructure() {
|
|
testDiag("Testing structure...");
|
|
|
|
PVDataCreatePtr factory = getPVDataCreate();
|
|
testOk1(factory.get()!=NULL);
|
|
|
|
testDiag("\tSimple structure serialization");
|
|
PVStructurePtr pvStructure = factory->createPVStructure(getStandardField()->timeStamp());
|
|
pvStructure->getLongField("secondsPastEpoch")->put(123);
|
|
pvStructure->getIntField("nanoSeconds")->put(456);
|
|
pvStructure->getIntField("userTag")->put(789);
|
|
|
|
serializationTest(pvStructure);
|
|
|
|
testDiag("\tComplex structure serialization");
|
|
pvStructure = factory->createPVStructure(
|
|
getStandardField()->structureArray(
|
|
getStandardField()->timeStamp(), "alarm,control,display,timeStamp")
|
|
);
|
|
// TODO fill with data
|
|
serializationTest(pvStructure);
|
|
}
|
|
|
|
void testUnion() {
|
|
testDiag("Testing union...");
|
|
|
|
PVDataCreatePtr factory = getPVDataCreate();
|
|
testOk1(factory.get()!=NULL);
|
|
|
|
|
|
PVDoublePtr doubleValue = factory->createPVScalar<PVDouble>();
|
|
PVIntPtr intValue = factory->createPVScalar<PVInt>();
|
|
|
|
testDiag("\tVariant union test");
|
|
|
|
PVUnionPtr variant = factory->createPVVariantUnion();
|
|
testOk1(variant.get()!=NULL);
|
|
testOk1(PVUnion::UNDEFINED_INDEX == variant->getSelectedIndex());
|
|
testOk1("" == variant->getSelectedFieldName());
|
|
serializationTest(variant);
|
|
|
|
variant->set(doubleValue);
|
|
testOk1(doubleValue.get() == variant->get().get());
|
|
testOk1(PVUnion::UNDEFINED_INDEX == variant->getSelectedIndex());
|
|
testOk1("" == variant->getSelectedFieldName());
|
|
serializationTest(variant);
|
|
|
|
variant->set(intValue);
|
|
testOk1(intValue.get() == variant->get().get());
|
|
testOk1(PVUnion::UNDEFINED_INDEX == variant->getSelectedIndex());
|
|
testOk1("" == variant->getSelectedFieldName());
|
|
serializationTest(variant);
|
|
|
|
variant->set(PVUnion::UNDEFINED_INDEX, doubleValue);
|
|
testOk1(doubleValue.get() == variant->get().get());
|
|
testOk1(PVUnion::UNDEFINED_INDEX == variant->getSelectedIndex());
|
|
|
|
variant->set(PVFieldPtr());
|
|
testOk1(NULL == variant->get().get());
|
|
|
|
testDiag("\tVariant union array test");
|
|
|
|
PVUnionArrayPtr variantArray = factory->createPVVariantUnionArray();
|
|
testOk1(variantArray.get()!=NULL);
|
|
|
|
variantArray->setLength(6);
|
|
PVUnionArray::svector data;
|
|
|
|
PVUnionPtr u = factory->createPVVariantUnion();
|
|
data.push_back(u);
|
|
|
|
u = factory->createPVVariantUnion();
|
|
u->set(factory->createPVStructure(getStandardField()->timeStamp()));
|
|
data.push_back(u);
|
|
|
|
u = factory->createPVVariantUnion();
|
|
u->set(factory->createPVStructure(getStandardField()->control()));
|
|
data.push_back(u);
|
|
|
|
data.push_back(PVUnionPtr());
|
|
|
|
variantArray->replace(freeze(data));
|
|
serializationTest(variantArray);
|
|
|
|
testDiag("\tVariant union test");
|
|
|
|
UnionConstPtr punion = getFieldCreate()->createFieldBuilder()->
|
|
add("doubleValue", pvDouble)->
|
|
add("intValue", pvInt)->
|
|
createUnion();
|
|
|
|
u = factory->createPVUnion(punion);
|
|
testOk1(NULL!=u.get());
|
|
|
|
// null union test
|
|
testOk1(NULL==u->get().get());
|
|
testOk1(PVUnion::UNDEFINED_INDEX == u->getSelectedIndex());
|
|
testOk1("" == u->getSelectedFieldName());
|
|
serializationTest(u);
|
|
|
|
u->select<PVDouble>("doubleValue")->put(12);
|
|
testOk1(12 == u->get<PVDouble>()->get());
|
|
testOk1(0 == u->getSelectedIndex());
|
|
testOk1("doubleValue" == u->getSelectedFieldName());
|
|
serializationTest(u);
|
|
|
|
u->select<PVInt>("intValue")->put(543);
|
|
testOk1(543 == u->get<PVInt>()->get());
|
|
testOk1(1 == u->getSelectedIndex());
|
|
testOk1("intValue" == u->getSelectedFieldName());
|
|
serializationTest(u);
|
|
|
|
u->select<PVInt>(1)->put(5432);
|
|
testOk1(5432 == u->get<PVInt>()->get());
|
|
serializationTest(u);
|
|
|
|
testOk1(NULL==u->select(PVUnion::UNDEFINED_INDEX).get());
|
|
testOk1(NULL==u->get().get());
|
|
testOk1(PVUnion::UNDEFINED_INDEX == u->getSelectedIndex());
|
|
testOk1("" == u->getSelectedFieldName());
|
|
serializationTest(u);
|
|
|
|
u->set("doubleValue", doubleValue);
|
|
testOk1(doubleValue.get() == u->get().get());
|
|
testOk1(0 == u->getSelectedIndex());
|
|
serializationTest(u);
|
|
|
|
try
|
|
{
|
|
u->set(1, doubleValue);
|
|
testFail("field type does not match, but set allowed");
|
|
}
|
|
catch (std::invalid_argument& ia)
|
|
{
|
|
// expected
|
|
testPass("PVUnion.set(int32, PVFieldPtr const&) field type does not match test");
|
|
}
|
|
|
|
try
|
|
{
|
|
u->select(120);
|
|
testFail("index out of bounds allowed");
|
|
}
|
|
catch (std::invalid_argument& ia)
|
|
{
|
|
// expected
|
|
testPass("PVUnion.select(int32) index out of bounds test");
|
|
}
|
|
|
|
try
|
|
{
|
|
u->select(-2);
|
|
testFail("index out of bounds allowed");
|
|
}
|
|
catch (std::invalid_argument& ia)
|
|
{
|
|
// expected
|
|
testPass("PVUnion.select(int32) index out of bounds test");
|
|
}
|
|
|
|
try
|
|
{
|
|
u->set(120, doubleValue);
|
|
testFail("index out of bounds allowed");
|
|
}
|
|
catch (std::invalid_argument& ia)
|
|
{
|
|
// expected
|
|
testPass("PVUnion.set(int32, PVFieldPtr const&) index out of bounds test");
|
|
}
|
|
|
|
testDiag("\tUnion array test");
|
|
|
|
PVUnionArrayPtr unionArray = factory->createPVUnionArray(getFieldCreate()->createUnionArray(punion));
|
|
testOk1(unionArray.get()!=NULL);
|
|
|
|
unionArray->setLength(6);
|
|
data.clear();
|
|
|
|
u = factory->createPVUnion(punion);
|
|
data.push_back(u);
|
|
|
|
u = factory->createPVUnion(punion);
|
|
u->select<PVDouble>(0)->put(12);
|
|
data.push_back(u);
|
|
|
|
u = factory->createPVUnion(punion);
|
|
u->select<PVInt>(1)->put(421);
|
|
data.push_back(u);
|
|
|
|
data.push_back(PVUnionPtr());
|
|
|
|
unionArray->replace(freeze(data));
|
|
serializationTest(unionArray);
|
|
|
|
}
|
|
|
|
void testStructureArray() {
|
|
testDiag("Testing structure array...");
|
|
|
|
PVDataCreatePtr factory = getPVDataCreate();
|
|
testOk1(factory.get()!=NULL);
|
|
|
|
StructureArrayConstPtr tstype(
|
|
getFieldCreate()->createStructureArray(getStandardField()->alarm()));
|
|
PVStructureArrayPtr pvArr = getPVDataCreate()->createPVStructureArray(tstype);
|
|
|
|
testDiag("empty array");
|
|
serializationTest(pvArr);
|
|
|
|
pvArr->setLength(10);
|
|
|
|
testDiag("All NULLs");
|
|
serializationTest(pvArr);
|
|
|
|
PVStructureArray::svector data(5);
|
|
|
|
data[1] = getPVDataCreate()->createPVStructure(getStandardField()->alarm());
|
|
data[4] = getPVDataCreate()->createPVStructure(getStandardField()->alarm());
|
|
|
|
pvArr->replace(freeze(data));
|
|
|
|
testDiag("Some NULLs");
|
|
serializationTest(pvArr);
|
|
}
|
|
|
|
|
|
void testStructureId() {
|
|
testDiag("Testing structureID...");
|
|
|
|
FieldCreatePtr fieldCreate = getFieldCreate();
|
|
|
|
StringArray fieldNames;
|
|
fieldNames.push_back("longField");
|
|
fieldNames.push_back("intField");
|
|
|
|
FieldConstPtrArray fields;
|
|
fields.push_back(fieldCreate->createScalar(pvLong));
|
|
fields.push_back(fieldCreate->createScalar(pvInt));
|
|
|
|
StructureConstPtr structureWithNoId = fieldCreate->createStructure(fieldNames, fields);
|
|
StructureConstPtr structure1 = fieldCreate->createStructure("id1", fieldNames, fields);
|
|
StructureConstPtr structure2 = fieldCreate->createStructure("id2", fieldNames, fields);
|
|
|
|
|
|
testOk1(structureWithNoId!=structure1);
|
|
testOk1(structure1!=structure2);
|
|
|
|
//serializationTest(structure1);
|
|
|
|
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(structure1);
|
|
serializationTest(pvStructure);
|
|
}
|
|
|
|
void serializatioTest(FieldConstPtr const & field)
|
|
{
|
|
buffer->clear();
|
|
|
|
// serialize
|
|
field->serialize(buffer, flusher);
|
|
|
|
// deserialize
|
|
buffer->flip();
|
|
|
|
FieldConstPtr deserializedField = getFieldCreate()->deserialize(buffer, control);
|
|
|
|
// must equal
|
|
testOk1(*field == *deserializedField);
|
|
}
|
|
|
|
void testIntrospectionSerialization()
|
|
{
|
|
testDiag("Testing introspection serialization...");
|
|
|
|
FieldCreatePtr factory = getFieldCreate();
|
|
testOk1(factory.get()!=NULL);
|
|
|
|
// be sure all is covered
|
|
for (int i = pvBoolean; i < pvString; i++)
|
|
{
|
|
ScalarType scalarType = static_cast<ScalarType>(i);
|
|
|
|
ScalarConstPtr scalar = factory->createScalar(scalarType);
|
|
serializatioTest(scalar);
|
|
|
|
ScalarArrayConstPtr array = factory->createScalarArray(scalarType);
|
|
serializatioTest(array);
|
|
}
|
|
|
|
// and a structure
|
|
StructureConstPtr structure = getStandardField()->timeStamp();
|
|
serializatioTest(structure);
|
|
|
|
// and a structure array
|
|
StructureArrayConstPtr structureArray = factory->createStructureArray(structure);
|
|
serializatioTest(structureArray);
|
|
|
|
// variant union
|
|
UnionConstPtr variant = factory->createVariantUnion();
|
|
serializatioTest(variant);
|
|
|
|
// variant array union
|
|
UnionArrayConstPtr variantArray = factory->createVariantUnionArray();
|
|
serializatioTest(variantArray);
|
|
|
|
// union
|
|
UnionConstPtr punion = factory->createFieldBuilder()->
|
|
add("double", pvDouble)->
|
|
addNestedStructureArray("nested")->
|
|
setId("nestedId")->
|
|
add("short", pvShort)->
|
|
add("long", pvLong)->
|
|
endNested()->
|
|
addArray("intArray", pvInt)->
|
|
createUnion();
|
|
serializatioTest(punion);
|
|
|
|
// union array
|
|
UnionArrayConstPtr punionArray = factory->createUnionArray(punion);
|
|
serializatioTest(punionArray);
|
|
}
|
|
|
|
void testStringCopy() {
|
|
String s1 = "abc";
|
|
String s2 = s1;
|
|
if (s1.c_str() != s2.c_str())
|
|
testDiag("implementation of epics::pvData::String assignment operator does not share content");
|
|
}
|
|
|
|
} // end namespace
|
|
|
|
MAIN(testSerialization) {
|
|
|
|
testPlan(213);
|
|
|
|
flusher = new SerializableControlImpl();
|
|
control = new DeserializableControlImpl();
|
|
buffer = new ByteBuffer(1<<16);
|
|
|
|
testStringCopy();
|
|
|
|
testIntrospectionSerialization();
|
|
testEquals();
|
|
|
|
testScalar();
|
|
testArray();
|
|
testStructure();
|
|
testStructureArray();
|
|
|
|
testUnion();
|
|
|
|
|
|
delete buffer;
|
|
delete control;
|
|
delete flusher;
|
|
|
|
epicsExitCallAtExits();
|
|
return testDone();
|
|
}
|
|
|