/** * 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 "utilpvt.h" #include "dataimpl.h" using namespace pvxs; namespace { void showSize() { testDiag("%s()", __func__); #define CASE(TYPE) testDiag("sizeof(" #TYPE ") = %u", unsigned(sizeof(TYPE))) CASE(Value); CASE(impl::FieldDesc); CASE(impl::FieldStorage); CASE(impl::StructTop); CASE(BitMask); #undef CASE } void testCode() { testDiag("%s()", __func__); testEq(TypeCode{TypeCode::UInt8}.size(), 1u); testEq(TypeCode{TypeCode::UInt16}.size(), 2u); testEq(TypeCode{TypeCode::UInt32}.size(), 4u); testEq(TypeCode{TypeCode::UInt64}.size(), 8u); testEq(TypeCode{TypeCode::UInt8A}.size(), 1u); testEq(TypeCode{TypeCode::UInt16A}.size(), 2u); testEq(TypeCode{TypeCode::UInt32A}.size(), 4u); testEq(TypeCode{TypeCode::UInt64A}.size(), 8u); testEq(TypeCode{TypeCode::Int8}.size(), 1u); testEq(TypeCode{TypeCode::Int16}.size(), 2u); testEq(TypeCode{TypeCode::Int32}.size(), 4u); testEq(TypeCode{TypeCode::Int64}.size(), 8u); testEq(TypeCode{TypeCode::Int8A}.size(), 1u); testEq(TypeCode{TypeCode::Int16A}.size(), 2u); testEq(TypeCode{TypeCode::Int32A}.size(), 4u); testEq(TypeCode{TypeCode::Int64A}.size(), 8u); } void testBasic() { testDiag("%s()", __func__); auto top = TypeDef(TypeCode::Struct, "simple_t", { Member(TypeCode::Float64, "value"), }).create(); testOk1(top.valid()); testEq(top.type(), TypeCode::Struct); { auto val = top["missing"]; testOk1(!val.valid()); testOk1(!val.isMarked()); testThrows([&val]() { val.from(4.2); }); } { auto val = top["value"]; testOk1(!!val.valid()); testOk1(!val.isMarked()); val.from(4.2); testEq(val.as(), 4.2); testOk1(!!val.isMarked()); } testEq(std::string(SB()<\n"); testEq(std::string(SB()< 10 [10]\n" " any -> 7 [7]\n" " anya -> 8 [8]\n" " arbitrary -> 5 [5]\n" " arbitrary.sarr -> 6 [6]\n" " choice -> 9 [9]\n" " timeStamp -> 2 [2]\n" " timeStamp.nanoseconds -> 4 [4]\n" " timeStamp.secondsPastEpoch -> 3 [3]\n" " value -> 1 [1]\n" " value : 1 [1]\n" " timeStamp : 2 [2]\n" " arbitrary : 5 [5]\n" " any : 7 [7]\n" " anya : 8 [8]\n" " choice : 9 [9]\n" " achoice : 10 [10]\n" "[1] double[] parent=[0] [1:2)\n" "[2] struct time_t parent=[0] [2:5)\n" " nanoseconds -> 2 [4]\n" " secondsPastEpoch -> 1 [3]\n" " secondsPastEpoch : 1 [3]\n" " nanoseconds : 2 [4]\n" "[3] uint64_t parent=[2] [3:4)\n" "[4] uint32_t parent=[2] [4:5)\n" "[5] struct parent=[0] [5:7)\n" " sarr -> 1 [6]\n" " sarr : 1 [6]\n" "[6] struct[] parent=[5] [6:7)\n" " [0] struct parent=[0] [0:2)\n" " value -> 1 [1]\n" " value : 1 [1]\n" " [1] double parent=[0] [1:2)\n" "[7] any parent=[0] [7:8)\n" "[8] any[] parent=[0] [8:9)\n" "[9] union parent=[0] [9:10)\n" " a -> 0 [0]\n" " b -> 1 [1]\n" " a : 0 [0]\n" " [0] float parent=[0] [0:1)\n" " b : 1 [1]\n" " [0] string parent=[0] [0:1)\n" "[10] union[] parent=[0] [10:11)\n" " [0] union parent=[0] [0:1)\n" " x -> 0 [0]\n" " y -> 1 [1]\n" " x : 0 [0]\n" " [0] float parent=[0] [0:1)\n" " y : 1 [1]\n" " [0] float parent=[0] [0:1)\n" ); // try to access all field Kinds // sub-struct and scalar val["timeStamp.secondsPastEpoch"] = 0x123456789abcdef0ull; // array of scalar { shared_array arr({1.0, 2.0}); val["value"] = arr.freeze().castTo(); } // Struct[] { auto fld = val["arbitrary.sarr"]; shared_array arr(3); arr[0] = fld.allocMember().update("value", 1.0); arr[1] = fld.allocMember(); arr[1]["value"] = 2.0; // leave [2] as null fld = arr.freeze(); testEq(val["arbitrary.sarr[0].value"].as(), 1.0); testEq(val["arbitrary.sarr[1].value"].as(), 2.0); } // Union val["choice->b"] = "test"; // Union[] { auto fld = val["achoice"]; shared_array arr(3); arr[0] = fld.allocMember(); arr[1] = fld.allocMember(); // leave [2] as null arr[0]["->x"] = 4.0; arr[1]["->y"] = 5.0; fld = arr.freeze().castTo(); testEq(fld["[1]"].as(), 5.0); testEq(val["achoice[1]"].as(), 5.0); testEq(val["achoice[1]->y"].as(), 5.0); } // Any { auto v = TypeDef(TypeCode::UInt32).create(); v = 42u; val["any"].from(v); testEq(v.as(), 42u); } // Any[] { auto fld = val["anya"]; shared_array arr(3); arr[0] = TypeDef(TypeCode::UInt32).create(); arr[1] = TypeDef(TypeCode::Struct, {Member(TypeCode::String, "q")}).create(); // leave [2] as null arr[0] = 123; arr[1]["q"] = "theq"; fld = arr.freeze().castTo(); testEq(fld["[0]"].as(), 123u); testEq(fld["[1].q"].as(), "theq"); } testStrEq(std::string(SB()< mem({ Member(TypeCode::Float64, "value"), }); { TypeDef def(TypeCode::Struct, "simple_t", mem); auto val = def.create(); testTrue(val.valid()); testStrEq(std::string(SB()< arr(1); arr[0] = val.allocMember().update("value", 42); val = arr.freeze(); testTrue(val.valid()); testStrEq(std::string(SB()< arr(1); arr[0] = val.allocMember().update("->value", 42); val = arr.freeze(); testTrue(val.valid()); testStrEq(std::string(SB()<one"] = 42; (void)top.cloneEmpty(); (void)top.clone(); } void testFormat() { testDiag("%s()", __func__); Value top(neckBolt()); top["scalar.i32"] = -42; top["scalar.u32"] = 42; top["scalar.b"] = true; top["scalar.f64"] = 123.5; top["scalar.s"] = "a \"test\""; top["scalar.wildcard"] = "simple"; top["scalar.choice->one"] = 1024; top["array.i32"] = shared_array({1,-1,2,-3}).freeze().castTo(); top["array.s"] = shared_array({"one", "two", "three"}).freeze().castTo(); { auto fld = top["array.wildcard"]; shared_array arr(2); auto temp = arr[0] = TypeDef(TypeCode::String).create(); // arr[1] left null temp = "simple"; fld = arr.freeze().castTo(); } { auto fld = top["array.choice"]; shared_array arr(3); (arr[0] = fld.allocMember())["->one"] = 1357; // arr[1] left null (arr[2] = fld.allocMember())["->two.ahalf"] = 2468; fld = arr.freeze().castTo(); } testStrEq(std::string(SB()< string = \"simple\"\n" "scalar.choice union\n" "scalar.choice->one int32_t = 1024\n" "array struct\n" "array.i32 int32_t[] = {4}[1, -1, 2, -3]\n" "array.s string[] = {3}[\"one\", \"two\", \"three\"]\n" "array.wildcard any[]\n" "array.wildcard[0] string = \"simple\"\n" "array.wildcard[1] null\n" "array.choice union[]\n" "array.choice[0] union\n" "array.choice[0]->one int32_t = 1357\n" "array.choice[1] null\n" "array.choice[2] union\n" "array.choice[2]->two struct\n" "array.choice[2]->two.ahalf int32_t = 2468\n" "array.more struct[] = {\?}[]\n" ); } } // namespace MAIN(testtype) { testPlan(56); testSetup(); showSize(); testCode(); testBasic(); testTypeDef(); testTypeDefDynamic(); testTypeDefAppend(); testOp(); testFormat(); cleanup_for_valgrind(); return testDone(); }