test iocsh functions

This commit is contained in:
Michael Davidsaver
2026-02-27 08:16:23 +00:00
parent ef7ef0f158
commit 1d182cb031
7 changed files with 185 additions and 4 deletions
+3 -1
View File
@@ -8,7 +8,6 @@
*/
#include <string>
#include <sstream>
#include <epicsThread.h>
#include <cantProceed.h>
@@ -16,6 +15,9 @@
#include "group.h"
#include "utilpvt.h"
// define printf macro after __attribute__ in event2.h
#include <epicsStdio.h>
namespace pvxs {
namespace ioc {
+3
View File
@@ -119,6 +119,7 @@ benchdata_SRCS += benchdata.cpp
TESTPROD_HOST += testpvalink
testpvalink_SRCS += testpvalink.cpp
testpvalink_SRCS += capturestd.cpp
testpvalink_SRCS += testioc_registerRecordDeviceDriver.cpp
testpvalink_LIBS += pvxsIoc pvxs $(EPICS_BASE_IOC_LIBS)
TESTS += testpvalink
@@ -134,6 +135,7 @@ TESTFILES += $(COMMON_DIR)/testioc.dbd
TESTPROD_HOST += testqsingle
testqsingle_SRCS += testqsingle
testqsingle_SRCS += capturestd.cpp
testqsingle_SRCS += testioc_registerRecordDeviceDriver.cpp
testqsingle_LIBS = pvxsIoc pvxs $(EPICS_BASE_IOC_LIBS)
TESTFILES += ../testqsingle.db
@@ -148,6 +150,7 @@ ifdef BASE_7_0
TESTPROD_HOST += testqgroup
testqgroup_SRCS += testqgroup
testqgroup_SRCS += capturestd.cpp
testqgroup_SRCS += testioc_registerRecordDeviceDriver.cpp
testqgroup_LIBS = pvxsIoc pvxs $(EPICS_BASE_IOC_LIBS)
TESTFILES += ../table.db
+59
View File
@@ -0,0 +1,59 @@
/**
* 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 <fstream>
#include <sstream>
#include <stdexcept>
#include <memory>
#include "capturestd.h"
#include <epicsUnitTest.h>
#include <epicsStdio.h>
static
std::string readFile(const std::string& filename)
{
std::ifstream t(filename.c_str());
std::stringstream buffer;
if (!t.is_open()) {
throw std::invalid_argument("Could not open filename " + filename);
}
buffer << t.rdbuf();
return buffer.str();
}
CaptureStd::CaptureStd(const std::function<void ()> &fn) {
std::shared_ptr<FILE>
out(fopen("testiocsh.out", "w+b"),
[](FILE* fp){
(void)fclose(fp);
}),
err(fopen("testiocsh.err", "w+b"),
[](FILE* fp){
(void)fclose(fp);
});
if(!out || !err)
testAbort("Unable to open/create testiocsh.out / .err");
epicsSetThreadStdout(out.get());
epicsSetThreadStderr(err.get());
try {
fn();
}catch(...){
epicsSetThreadStdout(nullptr);
epicsSetThreadStderr(nullptr);
throw;
}
out.reset();
err.reset();
m_out = readFile("testiocsh.out");
m_err = readFile("testiocsh.err");
}
+27
View File
@@ -0,0 +1,27 @@
/**
* 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.
*/
#ifndef CAPTURESTD_H
#define CAPTURESTD_H
#include <string>
#include <functional>
struct CaptureStd
{
std::string m_out, m_err;
CaptureStd(const std::function<void()>& fn);
const std::string& out() const {
return m_out;
}
const std::string& err() const {
return m_err;
}
};
#endif // CAPTURESTD_H
+24 -1
View File
@@ -6,6 +6,7 @@
#include <testMain.h>
#include <epicsExit.h>
#include <iocsh.h>
#include <dbLock.h>
#include <dbLink.h>
#include <recGbl.h>
@@ -33,6 +34,7 @@
#include "dblocker.h"
#include "qsrvpvt.h"
#include "pvalink.h"
#include "capturestd.h"
using namespace pvxs::ioc;
using namespace pvxs;
@@ -604,6 +606,26 @@ namespace {
ntndarray.close();
}
void testiocsh()
{
testDiag("==== %s ====", __func__);
{
CaptureStd cap([](){
iocshCmd("dbpvar \"\" 5");
});
testStrEq(cap.err(), "");
testStrMatch(".*PVA links in all records.*async:target conn=T.*", cap.out());
}
{
CaptureStd cap([](){
iocshCmd("dbjlr \"\" 5");
});
testStrEq(cap.err(), "");
testStrMatch(".*\'pva\': testToFromString:str1.*", cap.out());
}
}
} // namespace
@@ -611,7 +633,7 @@ extern "C" void testioc_registerRecordDeviceDriver(struct dbBase *);
MAIN(testpvalink)
{
testPlan(102);
testPlan(106);
testSetup();
pvxs::logger_config_env();
@@ -643,6 +665,7 @@ MAIN(testpvalink)
testAtomic();
testEnum();
testNTNDArray();
testiocsh();
}
catch (std::exception &e)
{
+16 -1
View File
@@ -19,6 +19,7 @@
#include "testioc.h"
#include "utilpvt.h"
#include "capturestd.h"
extern "C" {
extern int testioc_registerRecordDeviceDriver(struct dbBase*);
@@ -731,6 +732,19 @@ void testBatch()
testEq(ret["SUM.value"].as<int32_t>(), 3);
}
void testiocsh()
{
testDiag("%s", __func__);
{
CaptureStd cap([](){
iocshCmd("pvxgl 5 \"\"");
});
testStrEq(cap.err(), "");
testStrMatch(".*enm:ENUM.*enm:ENUM:INDEX.VAL has triggers.*", cap.out());
}
}
void testDbLoadGroup()
{
testDiag("%s", __func__);
@@ -753,7 +767,7 @@ void testDbLoadGroup()
MAIN(testqgroup)
{
testPlan(39);
testPlan(41);
testSetup();
{
generalTimeRegisterCurrentProvider("test", 1, &testTimeCurrent);
@@ -778,6 +792,7 @@ MAIN(testqgroup)
testConst();
testBatch();
testDbLoadGroup();
testiocsh();
}
// call epics atexits explicitly to handle older base w/o de-init hooks
epicsExitCallAtExits();
+53 -1
View File
@@ -18,11 +18,14 @@
#include <epicsExit.h>
#include <asTrapWrite.h>
#include <generalTimeSup.h>
#include <iocsh.h>
#include "dblocker.h"
#include "testioc.h"
#include "utilpvt.h"
#include "capturestd.h"
#if EPICS_VERSION_INT >= VERSION_INT(3, 15, 0, 2)
# define HAVE_lsi
#endif
@@ -947,11 +950,59 @@ void testMonitorDBE(TestClient& ctxt)
testEq(val["value"].as<int32_t>(), 43);
}
void testiocsh(TestClient& ctxt)
{
testDiag("%s", __func__);
TestSubscription sub(ctxt.monitor("test:ai")
.maskConnected(true)
.maskDisconnected(true));
auto val(sub.waitForUpdate());
{
CaptureStd cap([](){
iocshCmd("pvxsr 5");
});
testStrEq(cap.err(), "");
testStrMatch(".*EPICS_PVAS_AUTO_BEACON_ADDR_LIST=NO.*", cap.out());
testStrMatch(".*Source: __server.*", cap.out());
testStrMatch(".*test:nsec.*", cap.out());
testStrMatch(".*State: Running TCP_Port:.*", cap.out());
testStrMatch(".*test:ai TX=.*", cap.out());
}
{
CaptureStd cap([](){
iocshCmd("pvxsi");
});
testStrEq(cap.err(), "");
testStrMatch(".*Toolchain.*", cap.out());
testStrMatch(".*epicsThreadGetCPUs.*", cap.out());
testStrMatch(".*EPICS_PVAS_AUTO_BEACON_ADDR_LIST=.*", cap.out());
}
{
CaptureStd cap([](){
iocshCmd("pvxrefshow");
iocshCmd("pvxrefsave");
iocshCmd("pvxrefdiff");
});
testStrEq(cap.err(), "");
testStrMatch(".*StructTop.*", cap.out());
}
{
CaptureStd cap([](){
iocshCmd("pvxsl 5");
});
testStrEq(cap.err(), "");
testStrMatch(".*RECORDS.*test:ai.*", cap.out());
}
}
} // namespace
MAIN(testqsingle)
{
testPlan(99);
testPlan(113);
testSetup();
pvxs::logger_config_env();
generalTimeRegisterCurrentProvider("test", 1, &testTimeCurrent);
@@ -996,6 +1047,7 @@ MAIN(testqsingle)
testMonitorAIFilt(mctxt);
testMonitorDBEAlarm(mctxt);
testMonitorDBE(mctxt);
testiocsh(mctxt);
}
timeSim = false;
testPutBlock();