/** * Copyright - See the COPYRIGHT that is included with this distribution. * pvxs is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ #include #include #include #include #include "dataimpl.h" #include "pvaproto.h" namespace { using namespace pvxs; using namespace pvxs::impl; void testDecode1() { testDiag("%s", __func__); /* From PVA proto doc * * timeStamp_t * long secondsPastEpoch * int nanoSeconds * int userTag */ std::vector msg({ // update cache with key 0 0xFD, 0x00, 0x01, // structure 0x80, // ID "timeStamp_t" 0x0B, 0x74, 0x69, 0x6D, 0x65, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x5F, 0x74, // 3 members 0x03, // "secondsPastEpoch" 0x10, 0x73, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x73, 0x50, 0x61, 0x73, 0x74, 0x45, 0x70, 0x6F, 0x63, 0x68, // integer signed 8 bytes 0x23, // "nanoSeconds" 0x0B, 0x6E, 0x61, 0x6E, 0x6F, 0x53, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x73, // integer signed 4 bytes 0x22, // "userTag" 0x07, 0x75, 0x73, 0x65, 0x72, 0x54, 0x61, 0x67, // integer signed 4 bytes 0x22 }); std::vector descs; TypeStore cache; { FixedBuf buf(true, msg); from_wire(buf, descs, cache); testOk1(buf.good()); testEq(buf.size(), 0u)<<"Of "<second.size(), 4u); } } if(testOk1(!descs.empty())) { testEq(descs.size(), descs.front().size()); } // cat < 2 [2] secondsPastEpoch -> 1 [1] userTag -> 3 [3] secondsPastEpoch : 1 [1] nanoSeconds : 2 [2] userTag : 3 [3] [1] int64_t parent=[0] [1:2) [2] int32_t parent=[0] [2:3) [3] int32_t parent=[0] [3:4) )out" )<<"Actual:\n"< msg(NTScalar, NTScalar+sizeof(NTScalar)-1); std::vector descs; TypeStore cache; { FixedBuf buf(true, msg); from_wire(buf, descs, cache); testOk1(buf.good()); testEq(buf.size(), 0u)<<"remaining of "< 2 [2] alarm.message -> 5 [5] alarm.severity -> 3 [3] alarm.status -> 4 [4] timeStamp -> 6 [6] timeStamp.nanoseconds -> 8 [8] timeStamp.secondsPastEpoch -> 7 [7] timeStamp.userTag -> 9 [9] value -> 1 [1] value : 1 [1] alarm : 2 [2] timeStamp : 6 [6] [1] double[] parent=[0] [1:2) [2] struct alarm_t parent=[0] [2:6) message -> 3 [5] severity -> 1 [3] status -> 2 [4] severity : 1 [3] status : 2 [4] message : 3 [5] [3] int32_t parent=[2] [3:4) [4] int32_t parent=[2] [4:5) [5] string parent=[2] [5:6) [6] struct time_t parent=[0] [6:10) nanoseconds -> 2 [8] secondsPastEpoch -> 1 [7] userTag -> 3 [9] secondsPastEpoch : 1 [7] nanoseconds : 2 [8] userTag : 3 [9] [7] int64_t parent=[6] [7:8) [8] int32_t parent=[6] [8:9) [9] int32_t parent=[6] [9:10) )out" )<<"Actual:\n"< out; out.reserve(msg.size()); { VectorOutBuf buf(true, out); to_wire(buf, descs.data()); testOk1(buf.good()); out.resize(out.size()-buf.size()); } testEq(msg.size(), out.size()); testEq(msg, out); } // has a bit of everything... (except array of union) const uint8_t NTNDArray[] = "\x80\x16""epics:nt/NTNDArray:1.0\n" "\x05value\x81\x00\x0b" "\x0c""booleanValue\x08" "\tbyteValue(" "\nshortValue)" "\x08intValue*" "\tlongValue+" "\nubyteValue," "\x0bushortValue-" "\tuintValue." "\nulongValue/" "\nfloatValueJ" "\x0b""doubleValueK" "\x05""codec\x80\x07""codec_t\x02" "\x04name`" "\nparameters\x82" "\x0e""compressedSize#" "\x10uncompressedSize#" "\x08uniqueId\"" "\rdataTimeStamp\x80\x06time_t\x03" "\x10secondsPastEpoch#" "\x0bnanoseconds\"" "\x07userTag\"" "\x05""alarm\x80\x07""alarm_t\x03" "\x08severity\"" "\x06status\"" "\x07message`" "\ttimeStamp\x80\x06time_t\x03" "\x10secondsPastEpoch#" "\x0bnanoseconds\"" "\x07userTag\"" "\tdimension\x88\x80\x0b""dimension_t\x05" "\x04size\"" "\x06offset\"" "\x08""fullSize\"" "\x07""binning\"" "\x07reverse\x00" "\tattribute\x88\x80\x18""epics:nt/NTAttribute:1.0\x08" "\x04name`" "\x05value\x82" "\x04tagsh" "\ndescriptor`" "\x05""alarm\x80\x07""alarm_t\x03" "\x08severity\"" "\x06status\"" "\x07message`" "\ttimestamp\x80\x06time_t\x03" "\x10secondsPastEpoch#" "\x0bnanoseconds\"" "\x07userTag\"" "\nsourceType\"" "\x06source`"; void testXCodeNTNDArray() { testDiag("%s", __func__); std::vector msg(NTNDArray, NTNDArray+sizeof(NTNDArray)-1); std::vector descs; TypeStore cache; { FixedBuf buf(true, msg); from_wire(buf, descs, cache); testOk1(buf.good()); testEq(buf.size(), 0u)<<"remaining of "< 12 [12] alarm.message -> 15 [15] alarm.severity -> 13 [13] alarm.status -> 14 [14] attribute -> 21 [21] codec -> 2 [2] codec.name -> 3 [3] codec.parameters -> 4 [4] compressedSize -> 5 [5] dataTimeStamp -> 8 [8] dataTimeStamp.nanoseconds -> 10 [10] dataTimeStamp.secondsPastEpoch -> 9 [9] dataTimeStamp.userTag -> 11 [11] dimension -> 20 [20] timeStamp -> 16 [16] timeStamp.nanoseconds -> 18 [18] timeStamp.secondsPastEpoch -> 17 [17] timeStamp.userTag -> 19 [19] uncompressedSize -> 6 [6] uniqueId -> 7 [7] value -> 1 [1] value : 1 [1] codec : 2 [2] compressedSize : 5 [5] uncompressedSize : 6 [6] uniqueId : 7 [7] dataTimeStamp : 8 [8] alarm : 12 [12] timeStamp : 16 [16] dimension : 20 [20] attribute : 21 [21] [1] union parent=[0] [1:2) booleanValue -> 0 [0] byteValue -> 1 [1] doubleValue -> 10 [10] floatValue -> 9 [9] intValue -> 3 [3] longValue -> 4 [4] shortValue -> 2 [2] ubyteValue -> 5 [5] uintValue -> 7 [7] ulongValue -> 8 [8] ushortValue -> 6 [6] booleanValue : 0 [0] [0] bool[] parent=[0] [0:1) byteValue : 1 [1] [0] int8_t[] parent=[0] [0:1) shortValue : 2 [2] [0] int16_t[] parent=[0] [0:1) intValue : 3 [3] [0] int32_t[] parent=[0] [0:1) longValue : 4 [4] [0] int64_t[] parent=[0] [0:1) ubyteValue : 5 [5] [0] uint8_t[] parent=[0] [0:1) ushortValue : 6 [6] [0] uint16_t[] parent=[0] [0:1) uintValue : 7 [7] [0] uint32_t[] parent=[0] [0:1) ulongValue : 8 [8] [0] uint64_t[] parent=[0] [0:1) floatValue : 9 [9] [0] float[] parent=[0] [0:1) doubleValue : 10 [10] [0] double[] parent=[0] [0:1) [2] struct codec_t parent=[0] [2:5) name -> 1 [3] parameters -> 2 [4] name : 1 [3] parameters : 2 [4] [3] string parent=[2] [3:4) [4] any parent=[2] [4:5) [5] int64_t parent=[0] [5:6) [6] int64_t parent=[0] [6:7) [7] int32_t parent=[0] [7:8) [8] struct time_t parent=[0] [8:12) nanoseconds -> 2 [10] secondsPastEpoch -> 1 [9] userTag -> 3 [11] secondsPastEpoch : 1 [9] nanoseconds : 2 [10] userTag : 3 [11] [9] int64_t parent=[8] [9:10) [10] int32_t parent=[8] [10:11) [11] int32_t parent=[8] [11:12) [12] struct alarm_t parent=[0] [12:16) message -> 3 [15] severity -> 1 [13] status -> 2 [14] severity : 1 [13] status : 2 [14] message : 3 [15] [13] int32_t parent=[12] [13:14) [14] int32_t parent=[12] [14:15) [15] string parent=[12] [15:16) [16] struct time_t parent=[0] [16:20) nanoseconds -> 2 [18] secondsPastEpoch -> 1 [17] userTag -> 3 [19] secondsPastEpoch : 1 [17] nanoseconds : 2 [18] userTag : 3 [19] [17] int64_t parent=[16] [17:18) [18] int32_t parent=[16] [18:19) [19] int32_t parent=[16] [19:20) [20] struct[] parent=[0] [20:21) [0] struct dimension_t parent=[0] [0:6) binning -> 4 [4] fullSize -> 3 [3] offset -> 2 [2] reverse -> 5 [5] size -> 1 [1] size : 1 [1] offset : 2 [2] fullSize : 3 [3] binning : 4 [4] reverse : 5 [5] [1] int32_t parent=[0] [1:2) [2] int32_t parent=[0] [2:3) [3] int32_t parent=[0] [3:4) [4] int32_t parent=[0] [4:5) [5] bool parent=[0] [5:6) [21] struct[] parent=[0] [21:22) [0] struct epics:nt/NTAttribute:1.0 parent=[0] [0:15) alarm -> 5 [5] alarm.message -> 8 [8] alarm.severity -> 6 [6] alarm.status -> 7 [7] descriptor -> 4 [4] name -> 1 [1] source -> 14 [14] sourceType -> 13 [13] tags -> 3 [3] timestamp -> 9 [9] timestamp.nanoseconds -> 11 [11] timestamp.secondsPastEpoch -> 10 [10] timestamp.userTag -> 12 [12] value -> 2 [2] name : 1 [1] value : 2 [2] tags : 3 [3] descriptor : 4 [4] alarm : 5 [5] timestamp : 9 [9] sourceType : 13 [13] source : 14 [14] [1] string parent=[0] [1:2) [2] any parent=[0] [2:3) [3] string[] parent=[0] [3:4) [4] string parent=[0] [4:5) [5] struct alarm_t parent=[0] [5:9) message -> 3 [8] severity -> 1 [6] status -> 2 [7] severity : 1 [6] status : 2 [7] message : 3 [8] [6] int32_t parent=[5] [6:7) [7] int32_t parent=[5] [7:8) [8] string parent=[5] [8:9) [9] struct time_t parent=[0] [9:13) nanoseconds -> 2 [11] secondsPastEpoch -> 1 [10] userTag -> 3 [12] secondsPastEpoch : 1 [10] nanoseconds : 2 [11] userTag : 3 [12] [10] int64_t parent=[9] [10:11) [11] int32_t parent=[9] [11:12) [12] int32_t parent=[9] [12:13) [13] int32_t parent=[0] [13:14) [14] string parent=[0] [14:15) )out" )<<"Actual:\n"< out; out.reserve(msg.size()); { VectorOutBuf buf(true, out); to_wire(buf, descs.data()); testOk1(buf.good()); out.resize(out.size()-buf.size()); } testEq(msg.size(), out.size()); testEq(msg, out); } // test the common case for a pvRequest of caching an empty Struct void testEmptyRequest() { testDiag("%s", __func__); TypeStore registry; std::vector descs1; { uint8_t msg[] = "\xfd\x02\x00\x80\x00\x00"; FixedBuf buf(false, msg); from_wire(buf, descs1, registry); testOk1(buf.good()); testEq(buf.size(), 0u)<<"remaining of "< descs2; { uint8_t msg[] = "\xfe\x02\x00"; FixedBuf buf(false, msg); from_wire(buf, descs2, registry); testOk1(buf.good()); testEq(buf.size(), 0u)<<"remaining of "<