647 lines
22 KiB
C++
647 lines
22 KiB
C++
/* testPVdata.cpp */
|
|
/*
|
|
* Copyright information and license terms for this software can be
|
|
* found in the file LICENSE that is included with the distribution
|
|
*/
|
|
/* Author: Marty Kraimer Date: 2010.11 */
|
|
|
|
#include <cstddef>
|
|
#include <cstdlib>
|
|
#include <cstddef>
|
|
#include <string>
|
|
#include <cstdio>
|
|
|
|
#include <epicsUnitTest.h>
|
|
#include <testMain.h>
|
|
|
|
#include <pv/requester.h>
|
|
#include <pv/pvIntrospect.h>
|
|
#include <pv/pvData.h>
|
|
#include <pv/convert.h>
|
|
#include <pv/standardField.h>
|
|
#include <pv/standardPVField.h>
|
|
#include <pv/pvTimeStamp.h>
|
|
#include <pv/bitSet.h>
|
|
|
|
using namespace epics::pvData;
|
|
using std::tr1::static_pointer_cast;
|
|
using std::string;
|
|
using std::cout;
|
|
using std::endl;
|
|
|
|
static FieldCreatePtr fieldCreate;
|
|
static PVDataCreatePtr pvDataCreate;
|
|
static StandardFieldPtr standardField;
|
|
static StandardPVFieldPtr standardPVField;
|
|
static ConvertPtr convert;
|
|
static string alarmTimeStamp("alarm,timeStamp");
|
|
static string alarmTimeStampValueAlarm("alarm,timeStamp,valueAlarm");
|
|
static string allProperties("alarm,timeStamp,display,control,valueAlarm");
|
|
|
|
static void testCreatePVStructure()
|
|
{
|
|
PVStructurePtr pv0 = standardPVField->scalar(
|
|
pvDouble,alarmTimeStampValueAlarm);
|
|
PVScalarPtr pv1 = pvDataCreate->createPVScalar(pvString);
|
|
PVFieldPtrArray pvFields;
|
|
StringArray fieldNames;
|
|
pvFields.reserve(2);
|
|
fieldNames.reserve(2);
|
|
fieldNames.push_back("value");
|
|
fieldNames.push_back("extra");
|
|
pvFields.push_back(pv0);
|
|
pvFields.push_back(pv1);
|
|
PVStructurePtr pvParent = pvDataCreate->createPVStructure(
|
|
fieldNames,pvFields);
|
|
|
|
std::cout << "testCreatePVStructure PASSED" << std::endl;
|
|
}
|
|
|
|
static void testCreatePVStructureWithInvalidName()
|
|
{
|
|
testDiag("testCreatePVStructureWithInvalidName");
|
|
StringArray fieldNames;
|
|
fieldNames.push_back("ok");
|
|
fieldNames.push_back("this.is-wrong");
|
|
PVFieldPtrArray pvFields;
|
|
pvFields.push_back(pvDataCreate->createPVScalar(pvString));
|
|
pvFields.push_back(pvDataCreate->createPVScalar(pvInt));
|
|
try{
|
|
PVStructurePtr pvParent = pvDataCreate->createPVStructure(
|
|
fieldNames,pvFields);
|
|
testFail("Creation of invalid field name '%s' was allowed", fieldNames[1].c_str());
|
|
} catch(std::invalid_argument& e) {
|
|
testDiag("Exception: \"%s\"", e.what());
|
|
testPass("Creation of invalid field name '%s' fails as expected", fieldNames[1].c_str());
|
|
}
|
|
}
|
|
|
|
static void testPVScalarCommon(string /*fieldName*/,ScalarType stype)
|
|
{
|
|
PVScalarPtr pvScalar = pvDataCreate->createPVScalar(stype);
|
|
if(stype==pvBoolean) {
|
|
convert->fromString(pvScalar,string("true"));
|
|
} else {
|
|
convert->fromString(pvScalar,string("10"));
|
|
}
|
|
}
|
|
|
|
static void testPVScalarWithProperties(
|
|
string /*fieldName*/,ScalarType stype)
|
|
{
|
|
PVStructurePtr pvStructure;
|
|
bool hasValueAlarm = false;
|
|
bool hasBooleanAlarm = false;
|
|
bool hasDisplayControl = false;
|
|
switch(stype) {
|
|
case pvBoolean: {
|
|
pvStructure = standardPVField->scalar(
|
|
stype,alarmTimeStampValueAlarm);
|
|
hasBooleanAlarm = true;
|
|
PVBooleanPtr pvField = pvStructure->getSubField<PVBoolean>("value");
|
|
pvField->put(true);
|
|
break;
|
|
}
|
|
case pvByte: {
|
|
pvStructure = standardPVField->scalar(
|
|
stype,allProperties);
|
|
hasValueAlarm = true;
|
|
hasDisplayControl = true;
|
|
PVBytePtr pvField = pvStructure->getSubField<PVByte>("value");
|
|
pvField->put(127);
|
|
break;
|
|
}
|
|
case pvShort: {
|
|
pvStructure = standardPVField->scalar(
|
|
stype,allProperties);
|
|
hasValueAlarm = true;
|
|
hasDisplayControl = true;
|
|
PVShortPtr pvField = pvStructure->getSubField<PVShort>("value");
|
|
pvField->put(32767);
|
|
break;
|
|
}
|
|
case pvInt: {
|
|
pvStructure = standardPVField->scalar(
|
|
stype,allProperties);
|
|
hasValueAlarm = true;
|
|
hasDisplayControl = true;
|
|
PVIntPtr pvField = pvStructure->getSubField<PVInt>("value");
|
|
pvField->put((int32)0x80000000);
|
|
break;
|
|
}
|
|
case pvLong: {
|
|
pvStructure = standardPVField->scalar(
|
|
stype,allProperties);
|
|
hasValueAlarm = true;
|
|
hasDisplayControl = true;
|
|
PVLongPtr pvField = pvStructure->getSubField<PVLong>("value");
|
|
int64 value = 0x80000000;
|
|
value <<= 32;
|
|
value |= 0xffffffff;
|
|
pvField->put(value);
|
|
break;
|
|
}
|
|
case pvUByte: {
|
|
pvStructure = standardPVField->scalar(
|
|
stype,allProperties);
|
|
hasValueAlarm = true;
|
|
hasDisplayControl = true;
|
|
PVUBytePtr pvField = pvStructure->getSubField<PVUByte>("value");
|
|
pvField->put(255);
|
|
break;
|
|
}
|
|
case pvUShort: {
|
|
pvStructure = standardPVField->scalar(
|
|
stype,allProperties);
|
|
hasValueAlarm = true;
|
|
hasDisplayControl = true;
|
|
PVUShortPtr pvField = pvStructure->getSubField<PVUShort>("value");
|
|
pvField->put(65535);
|
|
break;
|
|
}
|
|
case pvUInt: {
|
|
pvStructure = standardPVField->scalar(
|
|
stype,allProperties);
|
|
hasValueAlarm = true;
|
|
hasDisplayControl = true;
|
|
PVUIntPtr pvField = pvStructure->getSubField<PVUInt>("value");
|
|
pvField->put((uint32)0x80000000);
|
|
break;
|
|
}
|
|
case pvULong: {
|
|
pvStructure = standardPVField->scalar(
|
|
stype,allProperties);
|
|
hasValueAlarm = true;
|
|
hasDisplayControl = true;
|
|
PVULongPtr pvField = pvStructure->getSubField<PVULong>("value");
|
|
int64 value = 0x80000000;
|
|
value <<= 32;
|
|
value |= 0xffffffff;
|
|
pvField->put(value);
|
|
break;
|
|
}
|
|
case pvFloat: {
|
|
pvStructure = standardPVField->scalar(
|
|
stype,allProperties);
|
|
hasValueAlarm = true;
|
|
hasDisplayControl = true;
|
|
PVFloatPtr pvField = pvStructure->getSubField<PVFloat>("value");
|
|
pvField->put(1.123e8);
|
|
break;
|
|
}
|
|
case pvDouble: {
|
|
pvStructure = standardPVField->scalar(
|
|
stype,allProperties);
|
|
hasValueAlarm = true;
|
|
hasDisplayControl = true;
|
|
PVDoublePtr pvField = pvStructure->getSubField<PVDouble>("value");
|
|
pvField->put(1.123e35);
|
|
break;
|
|
}
|
|
case pvString: {
|
|
pvStructure = standardPVField->scalar(
|
|
stype,alarmTimeStamp);
|
|
PVStringPtr pvField = pvStructure->getSubField<PVString>("value");
|
|
pvField->put(string("this is a string"));
|
|
break;
|
|
}
|
|
}
|
|
PVLongPtr seconds = pvStructure->getSubField<PVLong>(
|
|
string("timeStamp.secondsPastEpoch"));
|
|
testOk1(seconds.get()!=0);
|
|
seconds->put(123456789);
|
|
PVIntPtr nano = pvStructure->getSubField<PVInt>(string("timeStamp.nanoseconds"));
|
|
testOk1(nano.get()!=0);
|
|
nano->put(1000000);
|
|
PVIntPtr severity = pvStructure->getSubField<PVInt>(string("alarm.severity"));
|
|
testOk1(severity.get()!=0);
|
|
severity->put(2);
|
|
PVStringPtr message = pvStructure->getSubField<PVString>(string("alarm.message"));
|
|
testOk1(message.get()!=0);
|
|
message->put(string("messageForAlarm"));
|
|
if(hasDisplayControl) {
|
|
PVStringPtr desc = pvStructure->getSubField<PVString>(
|
|
string("display.description"));
|
|
testOk1(desc.get()!=0);
|
|
desc->put(string("this is a description"));
|
|
PVStringPtr format = pvStructure->getSubField<PVString>(
|
|
string("display.format"));
|
|
testOk1(format.get()!=0);
|
|
format->put(string("f10.2"));
|
|
PVStringPtr units = pvStructure->getSubField<PVString>(
|
|
string("display.units"));
|
|
testOk1(units.get()!=0);
|
|
units->put(string("SomeUnits"));
|
|
PVDoublePtr limit = pvStructure->getSubField<PVDouble>(
|
|
string("display.limitLow"));
|
|
testOk1(limit.get()!=0);
|
|
limit->put(0.0);
|
|
limit = pvStructure->getSubField<PVDouble>(
|
|
string("display.limitHigh"));
|
|
testOk1(limit.get()!=0);
|
|
limit->put(10.0);
|
|
limit = pvStructure->getSubField<PVDouble>(
|
|
string("control.limitLow"));
|
|
testOk1(limit.get()!=0);
|
|
limit->put(1.0);
|
|
limit = pvStructure->getSubField<PVDouble>(
|
|
string("control.limitHigh"));
|
|
testOk1(limit.get()!=0);
|
|
limit->put(9.0);
|
|
}
|
|
if(hasValueAlarm) {
|
|
PVBooleanPtr pvBoolean = pvStructure->getSubField<PVBoolean>("valueAlarm.active");
|
|
pvBoolean->put(true);
|
|
PVScalarPtr pvtemp = pvStructure->getSubField<PVScalar>("valueAlarm.lowAlarmLimit");
|
|
testOk1(pvtemp.get()!=0);
|
|
convert->fromDouble(pvtemp,1.0);
|
|
pvtemp = pvStructure->getSubField<PVScalar>("valueAlarm.highAlarmLimit");
|
|
testOk1(pvtemp.get()!=0);
|
|
convert->fromDouble(pvtemp,9.0);
|
|
severity = pvStructure->getSubField<PVInt>(
|
|
string("valueAlarm.lowAlarmSeverity"));
|
|
testOk1(severity.get()!=0);
|
|
severity->put(2);
|
|
severity = pvStructure->getSubField<PVInt>(
|
|
string("valueAlarm.highAlarmSeverity"));
|
|
testOk1(severity.get()!=0);
|
|
severity->put(2);
|
|
PVBooleanPtr active = pvStructure->getSubField<PVBoolean>(
|
|
string("valueAlarm.active"));
|
|
testOk1(active.get()!=0);
|
|
active->put(true);
|
|
}
|
|
if(hasBooleanAlarm) {
|
|
PVBooleanPtr pvBoolean = pvStructure->getSubField<PVBoolean>("valueAlarm.active");
|
|
pvBoolean->put(true);
|
|
severity = pvStructure->getSubField<PVInt>(
|
|
string("valueAlarm.falseSeverity"));
|
|
testOk1(severity.get()!=0);
|
|
severity->put(0);
|
|
severity = pvStructure->getSubField<PVInt>(
|
|
string("valueAlarm.trueSeverity"));
|
|
testOk1(severity.get()!=0);
|
|
severity->put(2);
|
|
severity = pvStructure->getSubField<PVInt>(
|
|
string("valueAlarm.changeStateSeverity"));
|
|
testOk1(severity.get()!=0);
|
|
severity->put(1);
|
|
}
|
|
}
|
|
|
|
static void testPVScalar()
|
|
{
|
|
testPVScalarCommon(string("boolean"),pvByte);
|
|
testPVScalarCommon(string("byte"),pvByte);
|
|
testPVScalarCommon(string("short"),pvShort);
|
|
testPVScalarCommon(string("int"),pvInt);
|
|
testPVScalarCommon(string("long"),pvLong);
|
|
testPVScalarCommon(string("ubyte"),pvUByte);
|
|
testPVScalarCommon(string("ushort"),pvUShort);
|
|
testPVScalarCommon(string("uint"),pvUInt);
|
|
testPVScalarCommon(string("ulong"),pvULong);
|
|
testPVScalarCommon(string("float"),pvFloat);
|
|
testPVScalarCommon(string("double"),pvDouble);
|
|
testPVScalarCommon(string("string"),pvString);
|
|
|
|
testPVScalarWithProperties(string("boolean"),pvBoolean);
|
|
testPVScalarWithProperties(string("byte"),pvByte);
|
|
testPVScalarWithProperties(string("short"),pvShort);
|
|
testPVScalarWithProperties(string("int"),pvInt);
|
|
testPVScalarWithProperties(string("long"),pvLong);
|
|
testPVScalarWithProperties(string("ubyte"),pvUByte);
|
|
testPVScalarWithProperties(string("ushort"),pvUShort);
|
|
testPVScalarWithProperties(string("uint"),pvUInt);
|
|
testPVScalarWithProperties(string("ulong"),pvULong);
|
|
testPVScalarWithProperties(string("float"),pvFloat);
|
|
testPVScalarWithProperties(string("double"),pvDouble);
|
|
testPVScalarWithProperties(string("string"),pvString);
|
|
|
|
std::cout << "testPVScalar PASSED" << std::endl;
|
|
}
|
|
|
|
|
|
static void testScalarArrayCommon(string /*fieldName*/,ScalarType stype)
|
|
{
|
|
PVStructurePtr pvStructure = standardPVField->scalarArray(
|
|
stype,alarmTimeStamp);
|
|
PVScalarArrayPtr scalarArray = pvStructure->getSubField<PVScalarArray>("value");
|
|
testOk1(scalarArray.get()!=0);
|
|
if(stype==pvBoolean) {
|
|
StringArray values(3);
|
|
values[0] = "true";
|
|
values[1] = "false";
|
|
values[2] = "true";
|
|
convert->fromStringArray(scalarArray, 0,3,values,0);
|
|
} else {
|
|
StringArray values(3);
|
|
values[0] = "0";
|
|
values[1] = "1";
|
|
values[2] = "2";
|
|
convert->fromStringArray(scalarArray, 0,3,values,0);
|
|
}
|
|
PVFieldPtr pvField = pvStructure->getSubField<PVInt>("alarm.status");
|
|
testOk1(pvField.get()!=0);
|
|
}
|
|
|
|
static void testScalarArray()
|
|
{
|
|
testScalarArrayCommon(string("boolean"),pvBoolean);
|
|
testScalarArrayCommon(string("byte"),pvByte);
|
|
testScalarArrayCommon(string("short"),pvShort);
|
|
testScalarArrayCommon(string("int"),pvInt);
|
|
testScalarArrayCommon(string("long"),pvLong);
|
|
testScalarArrayCommon(string("float"),pvFloat);
|
|
testScalarArrayCommon(string("double"),pvDouble);
|
|
testScalarArrayCommon(string("string"),pvString);
|
|
std::cout << "testScalarArray PASSED" << std::endl;
|
|
}
|
|
|
|
static void testRequest()
|
|
{
|
|
StringArray nullNames;
|
|
FieldConstPtrArray nullFields;
|
|
StringArray optionNames(1);
|
|
FieldConstPtrArray optionFields(1);
|
|
optionNames[0] = "process";
|
|
optionFields[0] = fieldCreate->createScalar(pvString);
|
|
StringArray recordNames(1);
|
|
FieldConstPtrArray recordFields(1);
|
|
recordNames[0] = "_options";
|
|
recordFields[0] = fieldCreate->createStructure(optionNames,optionFields);
|
|
StringArray fieldNames(2);
|
|
FieldConstPtrArray fieldFields(2);
|
|
fieldNames[0] = "alarm";
|
|
fieldFields[0] = fieldCreate->createStructure(nullNames,nullFields);
|
|
fieldNames[1] = "timeStamp";
|
|
fieldFields[1] = fieldCreate->createStructure(nullNames,nullFields);
|
|
StringArray topNames(2);
|
|
FieldConstPtrArray topFields(2);
|
|
topNames[0] = "record";
|
|
topFields[0] = fieldCreate->createStructure(recordNames,recordFields);
|
|
topNames[1] = "field";
|
|
topFields[1] = fieldCreate->createStructure(fieldNames,fieldFields);
|
|
StructureConstPtr topStructure = fieldCreate->createStructure(
|
|
topNames,topFields);
|
|
cout << *topStructure << endl;
|
|
PVStructurePtr pvTop = pvDataCreate->createPVStructure(topStructure);
|
|
cout << *pvTop << endl;
|
|
cout << *pvTop->getStructure() << endl;
|
|
PVStructurePtr xxx = pvTop->getSubField<PVStructure>("record");
|
|
cout << *xxx << endl;
|
|
xxx = pvTop->getSubField<PVStructure>("field");
|
|
cout << *xxx << endl;
|
|
PVStringPtr pvString = pvTop->getSubField<PVString>("record._options.process");
|
|
pvString->put("true");
|
|
cout << *pvTop << endl;
|
|
|
|
string subName("record._options.process");
|
|
PVFieldPtr pvField = pvTop->getSubField<PVString>(subName);
|
|
string fieldName = pvField->getFieldName();
|
|
string fullName = pvField->getFullName();
|
|
cout << "fieldName " << fieldName << " fullName " << fullName << endl;
|
|
|
|
testOk1(fieldName.compare("process")==0);
|
|
testOk1(fullName.compare(subName)==0);
|
|
|
|
}
|
|
|
|
#define STRINGIZE(A) #A
|
|
#define TEST_COPY(T, V) testCopyCase<T>(V, STRINGIZE(T))
|
|
|
|
template<typename T>
|
|
void testCopyCase(typename T::value_type val, const char* typeName)
|
|
{
|
|
typename T::shared_pointer pv = pvDataCreate->createPVScalar<T>();
|
|
pv->put(val);
|
|
|
|
typename T::shared_pointer pv2 = pvDataCreate->createPVScalar<T>();
|
|
pv2->copy(*pv);
|
|
|
|
testOk(*pv == *pv2, "testCopyCase (copy) for type '%s'", typeName);
|
|
|
|
typename T::shared_pointer pv3 = pvDataCreate->createPVScalar<T>();
|
|
pv3->copy(*pv);
|
|
|
|
testOk(*pv == *pv3, "testCopyCase (copyUnchecked) for type '%s'", typeName);
|
|
}
|
|
|
|
static void testCopy()
|
|
{
|
|
TEST_COPY(PVBoolean, 1);
|
|
TEST_COPY(PVByte, 12);
|
|
TEST_COPY(PVShort, 128);
|
|
TEST_COPY(PVInt, 128000);
|
|
TEST_COPY(PVLong, 128000000);
|
|
TEST_COPY(PVUByte, 12);
|
|
TEST_COPY(PVUShort, 128);
|
|
TEST_COPY(PVUInt, 128000);
|
|
TEST_COPY(PVULong, 128000000);
|
|
TEST_COPY(PVFloat, 12.8);
|
|
TEST_COPY(PVDouble, 8.12);
|
|
TEST_COPY(PVString, "jikes");
|
|
|
|
int32 testValue = 128;
|
|
|
|
// PVStructure test
|
|
PVStructurePtr pvStructure =
|
|
standardPVField->scalar(pvInt, alarmTimeStampValueAlarm);
|
|
pvStructure->getSubField<PVInt>("value")->put(testValue);
|
|
|
|
PVTimeStamp timeStamp;
|
|
timeStamp.attach(pvStructure->getSubField<PVStructure>("timeStamp"));
|
|
TimeStamp current;
|
|
current.getCurrent();
|
|
timeStamp.set(current);
|
|
|
|
PVStructurePtr pvStructureCopy =
|
|
standardPVField->scalar(pvInt, alarmTimeStampValueAlarm);
|
|
pvStructureCopy->copy(*pvStructure);
|
|
testOk(*pvStructure == *pvStructureCopy, "PVStructure copy");
|
|
|
|
|
|
PVStructurePtr pvStructureCopy2 =
|
|
standardPVField->scalar(pvInt, alarmTimeStampValueAlarm);
|
|
pvStructureCopy2->copyUnchecked(*pvStructure);
|
|
testOk(*pvStructure == *pvStructureCopy2, "PVStructure copyUnchecked");
|
|
|
|
BitSet mask(pvStructure->getNumberFields());
|
|
PVStructurePtr pvStructureCopy3 =
|
|
standardPVField->scalar(pvInt, alarmTimeStampValueAlarm);
|
|
PVStructurePtr pvStructureCopy4 =
|
|
standardPVField->scalar(pvInt, alarmTimeStampValueAlarm);
|
|
pvStructureCopy3->copyUnchecked(*pvStructure, mask);
|
|
testOk(*pvStructureCopy3 == *pvStructureCopy4, "PVStructure copyUnchecked w/ cleared mask");
|
|
|
|
mask.set(pvStructure->getSubField<PVInt>("value")->getFieldOffset());
|
|
pvStructureCopy3->copyUnchecked(*pvStructure, mask);
|
|
pvStructureCopy4->getSubField<PVInt>("value")->put(testValue);
|
|
testOk(*pvStructureCopy3 == *pvStructureCopy4, "PVStructure copyUnchecked w/ value mask only");
|
|
|
|
mask.set(pvStructure->getSubField<PVStructure>("timeStamp")->getFieldOffset());
|
|
PVStructurePtr pvStructureCopy5 =
|
|
standardPVField->scalar(pvInt, alarmTimeStampValueAlarm);
|
|
pvStructureCopy5->copyUnchecked(*pvStructure, mask);
|
|
testOk(*pvStructure == *pvStructureCopy5, "PVStructure copyUnchecked w/ value+timeStamp mask");
|
|
|
|
|
|
UnionConstPtr _union = fieldCreate->createFieldBuilder()->
|
|
add("doubleValue", pvDouble)->
|
|
add("intValue", pvInt)->
|
|
add("timeStamp",standardField->timeStamp())->
|
|
createUnion();
|
|
|
|
PVUnionPtr pvUnion = pvDataCreate->createPVUnion(_union);
|
|
PVUnionPtr pvUnion2 = pvDataCreate->createPVUnion(_union);
|
|
pvUnion2->copy(*pvUnion);
|
|
testOk(*pvUnion == *pvUnion2, "null PVUnion copy");
|
|
|
|
pvUnion->select<PVInt>("intValue")->put(123);
|
|
pvUnion2->copy(*pvUnion);
|
|
testOk(*pvUnion == *pvUnion2, "PVUnion scalar copy, to null PVUnion");
|
|
|
|
pvUnion->select("doubleValue");
|
|
pvUnion2->copy(*pvUnion);
|
|
testOk(*pvUnion == *pvUnion2, "PVUnion scalar copy, to different type PVUnion");
|
|
|
|
pvUnion->select<PVStructure>("timeStamp")->copy(
|
|
*pvStructure->getSubField<PVStructure>("timeStamp")
|
|
);
|
|
pvUnion2->copy(*pvUnion);
|
|
testOk(*pvUnion == *pvUnion2, "PVUnion PVStructure copy, to different type PVUnion");
|
|
}
|
|
|
|
static void testFieldAccess()
|
|
{
|
|
testDiag("Check methods for accessing structure fields");
|
|
|
|
StructureConstPtr tdef = fieldCreate->createFieldBuilder()->
|
|
add("test", pvInt)->
|
|
addNestedStructure("hello")->
|
|
add("world", pvInt)->
|
|
endNested()->
|
|
createStructure();
|
|
|
|
PVStructurePtr fld = pvDataCreate->createPVStructure(tdef);
|
|
|
|
PVIntPtr a = fld->getSubField<PVInt>("test");
|
|
testOk1(a.get() != NULL);
|
|
if(a.get()) {
|
|
PVIntPtr b = fld->getSubFieldT<PVInt>("test");
|
|
testOk(b.get()==a.get(), "%p == %p", b.get(), a.get());
|
|
} else
|
|
testSkip(1, "test doesn't exist?");
|
|
|
|
a = fld->getSubField<PVInt>("hello.world");
|
|
testOk1(a.get() != NULL);
|
|
if(a.get()) {
|
|
PVIntPtr b = fld->getSubFieldT<PVInt>("hello.world");
|
|
testOk(b.get()==a.get(), "%p == %p", b.get(), a.get());
|
|
} else
|
|
testSkip(1, "hello.world doesn't exist?");
|
|
|
|
// non-existent
|
|
testOk1(fld->getSubField<PVInt>("invalid").get()==NULL);
|
|
|
|
// wrong type
|
|
testOk1(fld->getSubField<PVDouble>("test").get()==NULL);
|
|
|
|
// intermediate struct non-existent
|
|
testOk1(fld->getSubField<PVDouble>("helo.world").get()==NULL);
|
|
|
|
// empty leaf field name
|
|
testOk1(fld->getSubField<PVDouble>("hello.").get()==NULL);
|
|
|
|
// empty field name
|
|
testOk1(fld->getSubField<PVDouble>("hello..world").get()==NULL);
|
|
testOk1(fld->getSubField<PVDouble>(".").get()==NULL);
|
|
|
|
// whitespace
|
|
testOk1(fld->getSubField<PVInt>(" test").get()==NULL);
|
|
|
|
// intermediate field not structure
|
|
testOk1(fld->getSubField<PVInt>("hello.world.invalid").get()==NULL);
|
|
|
|
// null string
|
|
try{
|
|
char * name = NULL;
|
|
fld->getSubFieldT<PVInt>(name);
|
|
testFail("missing required exception");
|
|
}catch(std::invalid_argument& e){
|
|
testPass("caught expected exception: %s", e.what());
|
|
}
|
|
|
|
// non-existent
|
|
try{
|
|
fld->getSubFieldT<PVInt>("invalid");
|
|
testFail("missing required exception");
|
|
}catch(std::runtime_error& e){
|
|
testPass("caught expected exception: %s", e.what());
|
|
}
|
|
|
|
// wrong type
|
|
try{
|
|
fld->getSubFieldT<PVDouble>("test");
|
|
testFail("missing required exception");
|
|
}catch(std::runtime_error& e){
|
|
testPass("caught expected exception: %s", e.what());
|
|
}
|
|
|
|
// empty leaf field name
|
|
try{
|
|
fld->getSubFieldT<PVDouble>("hello.");
|
|
testFail("missing required exception");
|
|
}catch(std::runtime_error& e){
|
|
testPass("caught expected exception: %s", e.what());
|
|
}
|
|
|
|
// empty field name
|
|
try{
|
|
fld->getSubFieldT<PVDouble>("hello..world");
|
|
testFail("missing required exception");
|
|
}catch(std::runtime_error& e){
|
|
testPass("caught expected exception: %s", e.what());
|
|
}
|
|
try{
|
|
fld->getSubFieldT<PVDouble>(".");
|
|
testFail("missing required exception");
|
|
}catch(std::runtime_error& e){
|
|
testPass("caught expected exception: %s", e.what());
|
|
}
|
|
|
|
// whitespace
|
|
try{
|
|
fld->getSubFieldT<PVDouble>(" test");
|
|
testFail("missing required exception");
|
|
}catch(std::runtime_error& e){
|
|
testPass("caught expected exception: %s", e.what());
|
|
}
|
|
|
|
// intermediate field not structure
|
|
try{
|
|
fld->getSubFieldT<PVDouble>("hello.world.invalid");
|
|
testFail("missing required exception");
|
|
}catch(std::runtime_error& e){
|
|
testPass("caught expected exception: %s", e.what());
|
|
}
|
|
}
|
|
|
|
MAIN(testPVData)
|
|
{
|
|
testPlan(243);
|
|
fieldCreate = getFieldCreate();
|
|
pvDataCreate = getPVDataCreate();
|
|
standardField = getStandardField();
|
|
standardPVField = getStandardPVField();
|
|
convert = getConvert();
|
|
testCreatePVStructure();
|
|
testCreatePVStructureWithInvalidName();
|
|
testPVScalar();
|
|
testScalarArray();
|
|
testRequest();
|
|
testCopy();
|
|
testFieldAccess();
|
|
return testDone();
|
|
}
|
|
|