/* * Copyright information and license terms for this software can be * found in the file LICENSE that is included with the distribution */ #include #include #include #include #include #include #include #include #include #if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1) # define USE_JSON #endif namespace pvd = epics::pvData; typedef std::vector lines_t; namespace { struct SB { std::ostringstream strm; operator std::string() { return strm.str(); } template SB& operator<<(const T& v) { strm< actual ::detail::testPassx testDiff(const std::string& expect, const std::string& actual, const std::string& msg = std::string()) { bool match = expect==actual; ::detail::testPassx ret(match); ret<=lhs.size() || Rp>=rhs.size()) { // reached end without match Lp = lhs.size(); Rp = rhs.size(); } for(size_t l=L; lL); // must make progress assert(Rp>R); L = Lp; R = Rp; // loop around and print matching line } } for(; LcreateFieldBuilder() ->setId("epics:nt/NTScalar:1.0") ->add("value", pvd::pvInt) ->add("alarm", pvd::getStandardField()->alarm()) ->add("timeStamp", pvd::getStandardField()->timeStamp()) ->createStructure()); void showNTScalarNumeric() { testDiag("%s", CURRENT_FUNCTION); pvd::PVStructurePtr input(pvd::getPVDataCreate()->createPVStructure(scalarNumeric)); input->getSubFieldT("value")->putFrom(-42); testDiff(" -42 \n", print(input->stream())); input->getSubFieldT("alarm.severity")->putFrom(1); input->getSubFieldT("alarm.status")->putFrom(1); input->getSubFieldT("alarm.message")->put("FOO"); testDiff(" -42 MINOR DEVICE FOO \n", print(input->stream())); } static const pvd::StructureConstPtr scalarString(pvd::getFieldCreate()->createFieldBuilder() ->setId("epics:nt/NTScalar:1.0") ->add("value", pvd::pvString) ->add("alarm", pvd::getStandardField()->alarm()) ->add("timeStamp", pvd::getStandardField()->timeStamp()) ->createStructure()); void showNTScalarString() { testDiag("%s", CURRENT_FUNCTION); pvd::PVStructurePtr input(pvd::getPVDataCreate()->createPVStructure(scalarString)); testDiff(" \n", print(input->stream())); input->getSubFieldT("value")->put("bar"); testDiff(" bar \n", print(input->stream())); input->getSubFieldT("alarm.severity")->putFrom(1); input->getSubFieldT("alarm.status")->putFrom(1); input->getSubFieldT("alarm.message")->put("FOO"); testDiff(" bar MINOR DEVICE FOO \n", print(input->stream())); } static const pvd::StructureConstPtr ntenum(pvd::getFieldCreate()->createFieldBuilder() ->setId("epics:nt/NTEnum:1.0") ->addNestedStructure("value") ->setId("enum_t") ->add("index", pvd::pvInt) ->addArray("choices", pvd::pvString) ->endNested() ->add("alarm", pvd::getStandardField()->alarm()) ->add("timeStamp", pvd::getStandardField()->timeStamp()) ->createStructure()); void showNTEnum() { testDiag("%s", CURRENT_FUNCTION); pvd::PVStructurePtr input(pvd::getPVDataCreate()->createPVStructure(ntenum)); testDiff(" (0) \n", print(input->stream()), "empty"); pvd::PVStringArray::svector sarr; sarr.push_back("one"); sarr.push_back("a two"); input->getSubFieldT("value.choices")->replace(pvd::freeze(sarr)); input->getSubFieldT("value.index")->put(0); testDiff(" (0) one\n", print(input->stream()), "one"); input->getSubFieldT("value.index")->put(1); testDiff(" (1) a two\n", print(input->stream()), "two"); testDiff("epics:nt/NTEnum:1.0 \n" " enum_t value (1) a two\n" " int index 1\n" " string[] choices [\"one\", \"a two\"]\n" " alarm_t alarm \n" " int severity 0\n" " int status 0\n" " string message \n" " time_t timeStamp \n" " long secondsPastEpoch 0\n" " int nanoseconds 0\n" " int userTag 0\n", print(input->stream().format(pvd::PVStructure::Formatter::Raw)), "two raw"); } static const pvd::StructureConstPtr table(pvd::getFieldCreate()->createFieldBuilder() ->setId("epics:nt/NTTable:1.0") ->addArray("labels", pvd::pvString) ->addNestedStructure("value") ->addArray("colA", pvd::pvInt) ->addArray("colB", pvd::pvString) ->endNested() ->add("alarm", pvd::getStandardField()->alarm()) ->add("timeStamp", pvd::getStandardField()->timeStamp()) ->createStructure()); void showNTTable() { testDiag("%s", CURRENT_FUNCTION); pvd::PVStructurePtr input(pvd::getPVDataCreate()->createPVStructure(table)); testDiff(" \n" "colA, colB\n" , print(input->stream()), "empty table"); pvd::PVStringArray::svector sarr; sarr.push_back("labelA"); sarr.push_back("label B"); input->getSubFieldT("labels")->replace(pvd::freeze(sarr)); pvd::PVIntArray::svector iarr; iarr.push_back(1); iarr.push_back(2); iarr.push_back(3); iarr.push_back(42); // will not be shown input->getSubFieldT("value.colA")->replace(pvd::freeze(iarr)); sarr.push_back("one\x7f"); sarr.push_back("two words"); sarr.push_back("A '\"'"); input->getSubFieldT("value.colB")->replace(pvd::freeze(sarr)); testDiff(" \n" "labelA, \"label B\"\n" " 1, one\\x7F\n" " 2, \"two words\"\n" " 3, \"A \\'\"\"\\'\"\n" , print(input->stream()), "with data"); } static const pvd::StructureConstPtr everything(pvd::getFieldCreate()->createFieldBuilder() ->setId("omg") ->add("scalar", pvd::pvString) ->addArray("scalarArray", pvd::pvString) ->addNestedStructure("below") ->add("A", pvd::pvInt) ->addNestedUnion("select") ->add("one", pvd::pvInt) ->add("two", pvd::pvInt) ->endNested() ->addNestedUnionArray("arrselect") ->add("foo", pvd::pvInt) ->add("bar", pvd::pvInt) ->endNested() ->addNestedStructureArray("astruct") ->add("red", pvd::pvInt) ->add("blue", pvd::pvInt) ->endNested() ->endNested() ->add("anything", pvd::getFieldCreate()->createVariantUnion()) ->add("arrayany", pvd::getFieldCreate()->createVariantUnionArray()) ->createStructure()); void testRaw() { testDiag("%s", CURRENT_FUNCTION); pvd::PVStructurePtr input(pvd::getPVDataCreate()->createPVStructure(everything)); { pvd::PVStringArray::svector temp; temp.push_back("hello"); temp.push_back("world\x7f"); input->getSubFieldT("scalarArray")->replace(pvd::freeze(temp)); } testDiff("omg \n" " string scalar \n" // bit 1 " string[] scalarArray [\"hello\", \"world\\x7F\"]\n" " structure below\n" " int A 0\n" // bit 4 " union select\n" " (none)\n" " union[] arrselect\n" " structure[] astruct\n" " any anything\n" " (none)\n" " any[] arrayany\n" , print(input->stream())); testDiff("omg \n" " string scalar \n" " structure below\n" " int A 0\n" , print(input->stream().show(pvd::BitSet().set(1).set(4)))); testDiff("omg \n" "\033[1m string scalar \n" "\033[0m\033[1m string[] scalarArray [\"hello\", \"world\\x7F\"]\n" "\033[0m structure below\n" "\033[1m int A 0\n" "\033[0m union select\n" " (none)\n" " union[] arrselect\n" " structure[] astruct\n" " any anything\n" " (none)\n" " any[] arrayany\n" , print(input->stream() .mode(pvd::PVStructure::Formatter::ANSI) // force use of escapes .highlight(pvd::BitSet().set(1).set(2).set(4)) )); } void testEscape() { testDiag("%s", CURRENT_FUNCTION); testEqual("hello world", std::string(SB()<