diff --git a/test/Makefile b/test/Makefile index 3d04f1e..e721b39 100644 --- a/test/Makefile +++ b/test/Makefile @@ -46,6 +46,10 @@ TESTPROD += testinfo testinfo_SRCS += testinfo.cpp TESTS += testinfo +TESTPROD += testget +testget_SRCS += testget.cpp +TESTS += testget + TESTPROD += dummyserv dummyserv_SRCS += dummyserv.cpp # not a unittest diff --git a/test/testget.cpp b/test/testget.cpp new file mode 100644 index 0000000..76de716 --- /dev/null +++ b/test/testget.cpp @@ -0,0 +1,230 @@ +/** + * 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 +#include +#include +#include +#include +#include +#include + +namespace { +using namespace pvxs; + +struct Tester { + Value initial; + server::SharedPV mbox; + server::Server serv; + client::Context cli; + + Tester() + :initial(nt::NTScalar{TypeCode::Int32}.create()) + ,mbox(server::SharedPV::buildReadonly()) + ,serv(server::Config::localhost() + .build() + .addPV("mailbox", mbox)) + ,cli(serv.clientConfig().build()) + { + testShow()<<"Server:\n"<(), 42); + } else { + testSkip(1, "timeout"); + } + } + + void loopback() + { + testShow()<<__func__; + + mbox.open(initial); + serv.start(); + + testWait(); + } + + void lazy() + { + testShow()<<__func__; + + std::atomic onFC{false}, onLD{false}; + + mbox.onFirstConnect([this, &onFC](){ + testShow()<<__func__; + + mbox.open(initial); + onFC.store(true); + }); + mbox.onLastDisconnect([this, &onLD](){ + testShow()<<__func__; + mbox.close(); + onLD.store(true); + }); + + serv.start(); + + testWait(); + + serv.stop(); + + testOk1(!mbox.isOpen()); + testOk1(!!onFC.load()); + testOk1(!!onLD.load()); + } + + void timeout() + { + testShow()<<__func__; + + client::Result actual; + epicsEvent done; + + // server not started + + auto op = cli.info("mailbox") + .result([&actual, &done](client::Result&& result) { + actual = std::move(result); + done.trigger(); + }) + .exec(); + + cli.hurryUp(); + + testOk1(!done.wait(1.1)); + } + + void cancel() + { + testShow()<<__func__; + + client::Result actual; + epicsEvent done; + + serv.start(); + + // not storing Operation -> immediate cancel() + cli.info("mailbox") + .result([&actual, &done](client::Result&& result) { + actual = std::move(result); + done.trigger(); + }) + .exec(); + + cli.hurryUp(); + + testOk1(!done.wait(2.1)); + } +}; + +struct ErrorSource : public server::Source +{ + const bool phase = false; + const Value type; + explicit ErrorSource(bool phase) + :phase(phase) + ,type(nt::NTScalar{TypeCode::Int32}.create()) + {} + + virtual void onSearch(Search &op) override final + { + for(auto& name : op) { + name.claim(); + } + } + virtual void onCreate(std::unique_ptr &&op) override final + { + auto chan = std::move(op); + + chan->onOp([this](std::unique_ptr&& op) { + if(!phase) { + op->error("haha"); + return; + } + op->onGet([](std::unique_ptr&& op) { + op->error("nice try"); + }); + op->connect(type); + }); + } +}; + +void testError(bool phase) +{ + testShow()<<__func__<<" phase="<(phase)) + .start(); + + auto cli = serv.clientConfig().build(); + + client::Result actual; + epicsEvent done; + + auto op = cli.get("mailbox") + .result([&actual, &done](client::Result&& result) { + actual = std::move(result); + done.trigger(); + }) + .exec(); + + cli.hurryUp(); + + if(testOk1(done.wait(5.0))) { + testThrows([&actual]() { + auto val = actual(); + testShow()<<"unexpected result\n"<