manual merge

This commit is contained in:
Matej Sekoranja
2016-03-02 13:34:05 +01:00
39 changed files with 2180 additions and 1413 deletions

View File

@@ -3,7 +3,7 @@
SRC_DIRS += $(PVACCESS_TEST)/remote
TESTPROD_HOST += testChannelAccess
testChannelAccess_SRCS = testChannelAccess channelAccessIFTest
testChannelAccess_SRCS = channelAccessIFTest.cpp
testHarness_SRCS += testChannelAccess.cpp channelAccessIFTest.cpp
TESTS += testChannelAccess
@@ -48,3 +48,5 @@ rpcClientExample_SRCS += rpcClientExample.cpp
PROD_HOST += pipelineServiceExample
pipelineServiceExample_SRCS += pipelineServiceExample.cpp
TESTPROD_HOST += testClientFactory
testClientFactory_SRCS += testClientFactory.cpp

View File

@@ -21,6 +21,9 @@
#include "channelAccessIFTest.h"
//#define ENABLE_STRESS_TESTS
#define TESTSERVERNOMAIN
#include "testServer.cpp"
using namespace std::tr1;
@@ -38,14 +41,45 @@ std::string ChannelAccessIFTest::TEST_SUMRPC_CHANNEL_NAME = "testSum";
// double[] value
std::string ChannelAccessIFTest::TEST_ARRAY_CHANNEL_NAME = "testArray1";
#ifdef ENABLE_STRESS_TESTS
#define EXTRA_STRESS_TESTS 5
#else
#define EXTRA_STRESS_TESTS 0
#endif
namespace {
struct ScopedClientFactory {
ScopedClientFactory() { ClientFactory::start(); }
~ScopedClientFactory() { ClientFactory::stop(); }
};
}
int ChannelAccessIFTest::runAllTest() {
#ifdef ENABLE_STRESS_TESTS
testPlan(158);
#else
testPlan(153);
#endif
testPlan(153+EXTRA_STRESS_TESTS);
Configuration::shared_pointer base_config(ConfigurationBuilder()
//.add("EPICS_PVA_DEBUG", "3")
.add("EPICS_PVAS_INTF_ADDR_LIST", "127.0.0.1")
.add("EPICS_PVA_ADDR_LIST", "127.0.0.1")
.add("EPICS_PVA_AUTO_ADDR_LIST","0")
.add("EPICS_PVA_SERVER_PORT", "0")
.add("EPICS_PVA_BROADCAST_PORT", "0")
.push_map()
.build());
TestServer::shared_pointer tstserv(new TestServer(base_config));
tstserv->start();
testDiag("TestServer on ports TCP=%u UDP=%u\n",
tstserv->getServerPort(),
tstserv->getBroadcastPort());
ConfigurationFactory::registerConfiguration("pvAccess-client",
ConfigurationBuilder()
.push_config(base_config)
.add("EPICS_PVA_BROADCAST_PORT", tstserv->getBroadcastPort())
.push_map()
.build());
ScopedClientFactory SCF;
test_implementation();
test_providerName();
@@ -2348,3 +2382,30 @@ PVStructure::shared_pointer ChannelAccessIFTest::createArrayPvRequest() {
pvFieldName->put("value");
return pvRequest;
}
class ChannelAccessIFRemoteTest: public ChannelAccessIFTest {
public:
virtual ChannelProvider::shared_pointer getChannelProvider() {
return getChannelProviderRegistry()->getProvider(
"pva");
}
virtual long getTimeoutSec() {
return 3;
}
virtual bool isLocal() { return false;}
};
MAIN(testChannelAccess)
{
SET_LOG_LEVEL(logLevelError);
ChannelAccessIFRemoteTest caRemoteTest;
return caRemoteTest.runAllTest();
}

View File

@@ -1,104 +0,0 @@
/*
* testChannelAccess.cpp
*/
#ifdef _WIN32
#define NOMINMAX
#endif
// TODO not nice
// disable buggy boost enable_shared_from_this assert code
#define BOOST_DISABLE_ASSERTS
#define TESTSERVERNOMAIN
#include <envDefs.h>
#include <epicsExit.h>
#include <epicsUnitTest.h>
#include <testMain.h>
#include <pv/serverContext.h>
#include <pv/clientFactory.h>
#include "channelAccessIFTest.h"
#include "testServer.cpp"
class ServerContextAction : public Runnable {
public:
ServerContextAction():
m_serverThread(){}
virtual void run()
{
testServer(0);
}
void stop() {
testServerShutdown();
}
void start() {
m_serverThread.reset(new epics::pvData::Thread("pvAccess", highPriority, this));
}
private:
auto_ptr<epics::pvData::Thread> m_serverThread;
};
class ChannelAccessIFRemoteTest: public ChannelAccessIFTest {
public:
ChannelAccessIFRemoteTest(): m_serverContextAction()
{
m_serverContextAction.start();
ClientFactory::start();
}
virtual ChannelProvider::shared_pointer getChannelProvider() {
return getChannelProviderRegistry()->getProvider(
"pva");
}
virtual long getTimeoutSec() {
return 3;
}
virtual bool isLocal() { return false;}
~ChannelAccessIFRemoteTest() {
m_serverContextAction.stop();
ClientFactory::stop();
// shutdown SIGSEG problems
epicsThreadSleep(2.0);
}
private:
ServerContextAction m_serverContextAction;
};
MAIN(testChannelAccess)
{
// note: this leaks memory (uses putenv)
epicsEnvSet("EPICS_PVA_ADDR_LIST", "127.0.0.1");
epicsEnvSet("EPICS_PVA_AUTO_ADDR_LIST", "0");
SET_LOG_LEVEL(logLevelError);
ChannelAccessIFRemoteTest caRemoteTest;
return caRemoteTest.runAllTest();
}

View File

@@ -0,0 +1,15 @@
#include <epicsExit.h>
#include <pv/clientFactory.h>
#include <pv/pvAccess.h>
int main()
{
epics::pvAccess::ClientFactory::start();
epics::pvAccess::getChannelProviderRegistry()->getProvider("pva");
epics::pvAccess::ClientFactory::stop();
//epicsThreadSleep ( 3.0 );
//epicsExitCallAtExits();
return 0;
}

View File

@@ -22,6 +22,33 @@ namespace epics {
namespace pvAccess {
struct sender_break : public connection_closed_exception
{
sender_break() : connection_closed_exception("break") {}
};
struct TransportSenderDisconnect: public TransportSender {
void unlock() {}
void lock() {}
void send(ByteBuffer *buffer, TransportSendControl *control)
{
control->flush(true);
throw sender_break();
}
};
struct TransportSenderSignal: public TransportSender {
Event *evt;
TransportSenderSignal(Event& evt) :evt(&evt) {}
void unlock() {}
void lock() {}
void send(ByteBuffer *buffer, TransportSendControl *control)
{
evt->signal();
}
};
class PVAMessage {
public:
@@ -257,13 +284,6 @@ namespace epics {
}
void endBlockedProcessSendQueue() {
//TODO not thread safe
_blockingProcessQueue = false;
_sendQueue.wakeup();
}
void close() { _closedCount++; }
bool isOpen() { return _closedCount == 0; }
@@ -288,6 +308,10 @@ namespace epics {
void sendCompleted() { _sendCompletedCount++; }
void breakSender() {
enqueueSendRequest(std::tr1::shared_ptr<TransportSender>(new TransportSenderDisconnect()));
}
bool terminated() { return false; }
void cachedSerialize(
@@ -326,6 +350,8 @@ namespace epics {
}
const osiSockAddr* getRemoteAddress() const { return 0; }
std::string dummyRemoteName;
const std::string& getRemoteName() const {return dummyRemoteName;}
epics::pvData::int8 getRevision() const
{
@@ -412,7 +438,7 @@ namespace epics {
public:
int runAllTest() {
testPlan(5882);
testPlan(5883);
testHeaderProcess();
testInvalidHeaderMagic();
testInvalidHeaderSegmentedInNormal();
@@ -438,7 +464,6 @@ namespace epics {
testSendException();
testSendHugeMessagePartes();
testRecipient();
testClearSendQueue();
testInvalidArguments();
testDefaultModes();
testEnqueueSendRequestExceptionThrown();
@@ -2223,7 +2248,6 @@ namespace epics {
"%s: codec._closedCount == 1", CURRENT_FUNCTION);
}
class TransportSenderForTestEnqueueSendRequest:
public TransportSender {
public:
@@ -2290,7 +2314,10 @@ namespace epics {
// process
codec.enqueueSendRequest(sender);
codec.enqueueSendRequest(sender2);
codec.processSendQueue();
codec.breakSender();
try{
codec.processSendQueue();
}catch(sender_break&) {}
codec.transferToReadBuffer();
@@ -2430,11 +2457,16 @@ namespace epics {
//was processed
testOk(0 == codec._sendCompletedCount,
"%s: 0 == codec._sendCompletedCount", CURRENT_FUNCTION);
testOk1(!codec.sendQueueEmpty());
codec.processSendQueue();
codec.breakSender();
try{
codec.processSendQueue();
}catch(sender_break&) {}
testOk(1 == codec._sendCompletedCount,
"%s: 1 == codec._sendCompletedCount", CURRENT_FUNCTION);
testOk1(codec.sendQueueEmpty());
codec.transferToReadBuffer();
@@ -2483,6 +2515,13 @@ namespace epics {
"%s: 0 == codec.getSendBuffer()->getPosition()",
CURRENT_FUNCTION);
testOk1(codec.sendQueueEmpty());
testDiag("%u %u", (unsigned)codec._scheduleSendCount,
(unsigned)codec._sendCompletedCount);
testOk1(3 == codec._scheduleSendCount);
testOk1(1 == codec._sendCompletedCount);
// now queue is empty and thread is right
codec.enqueueSendRequest(sender2, PVA_MESSAGE_HEADER_SIZE);
@@ -2491,12 +2530,17 @@ namespace epics {
"%s: PVA_MESSAGE_HEADER_SIZE == "
"codec.getSendBuffer()->getPosition()",
CURRENT_FUNCTION);
testOk(3 == codec._scheduleSendCount,
"%s: 3 == codec._scheduleSendCount", CURRENT_FUNCTION);
testOk(1 == codec._sendCompletedCount,
"%s: 1 == codec._sendCompletedCount", CURRENT_FUNCTION);
codec.processWrite();
testDiag("%u %u", (unsigned)codec._scheduleSendCount,
(unsigned)codec._sendCompletedCount);
testOk1(4 == codec._scheduleSendCount);
testOk1(1 == codec._sendCompletedCount);
codec.breakSender();
try{
codec.processWrite();
}catch(sender_break&) {}
testOk(2 == codec._sendCompletedCount,
"%s: 2 == codec._sendCompletedCount", CURRENT_FUNCTION);
@@ -2575,7 +2619,10 @@ namespace epics {
// process
codec.enqueueSendRequest(sender);
codec.processSendQueue();
codec.breakSender();
try{
codec.processSendQueue();
}catch(sender_break&) {}
codec.transferToReadBuffer();
@@ -2664,7 +2711,7 @@ namespace epics {
// process
codec.enqueueSendRequest(sender);
codec.breakSender();
try
{
codec.processSendQueue();
@@ -2781,7 +2828,10 @@ namespace epics {
// process
codec.enqueueSendRequest(sender);
codec.processSendQueue();
codec.breakSender();
try{
codec.processSendQueue();
}catch(sender_break&) {}
codec.addToReadBuffer();
@@ -2886,37 +2936,6 @@ namespace epics {
TestCodec &_codec;
};
void testClearSendQueue()
{
testDiag("BEGIN TEST %s:", CURRENT_FUNCTION);
TestCodec codec(DEFAULT_BUFFER_SIZE,DEFAULT_BUFFER_SIZE);
std::tr1::shared_ptr<TransportSender> sender =
std::tr1::shared_ptr<TransportSender>(
new TransportSenderForTestClearSendQueue(codec));
std::tr1::shared_ptr<TransportSender> sender2 =
std::tr1::shared_ptr<TransportSender>(
new TransportSender2ForTestClearSendQueue(codec));
codec.enqueueSendRequest(sender);
codec.enqueueSendRequest(sender2);
codec.clearSendQueue();
codec.processSendQueue();
testOk(0 == codec.getSendBuffer()->getPosition(),
"%s: 0 == codec.getSendBuffer()->getPosition()",
CURRENT_FUNCTION);
testOk(0 == codec._writeBuffer.getPosition(),
"%s: 0 == codec._writeBuffer.getPosition()",
CURRENT_FUNCTION);
}
void testInvalidArguments()
{
testDiag("BEGIN TEST %s:", CURRENT_FUNCTION);
@@ -3128,6 +3147,7 @@ namespace epics {
TransportSendControl* control)
{
_codec.putControlMessage((int8_t)0x01, 0x00112233);
_codec.flush(true);
}
private:
@@ -3135,16 +3155,20 @@ namespace epics {
};
class ValueHolder {
class ValueHolder : public Runnable {
public:
ValueHolder(
TestCodec &testCodec,
AtomicValue<bool> &processTreadExited):
_testCodec(testCodec),
_processTreadExited(processTreadExited) {}
ValueHolder(TestCodec &testCodec):
_testCodec(testCodec) {}
TestCodec &_testCodec;
AtomicValue<bool> & _processTreadExited;
Event waiter;
virtual void run() {
waiter.signal();
try{
_testCodec.processSendQueue();
}catch(sender_break&) {}
}
};
@@ -3155,56 +3179,40 @@ namespace epics {
TestCodec codec(DEFAULT_BUFFER_SIZE,
DEFAULT_BUFFER_SIZE, true);
_processTreadExited.getAndSet(false);
std::tr1::shared_ptr<TransportSender> sender =
std::tr1::shared_ptr<TransportSender>(
new TransportSenderForTestBlockingProcessQueueTest(codec));
ValueHolder valueHolder(codec, _processTreadExited);
ValueHolder valueHolder(codec);
Event done;
epicsThreadCreate(
"testBlockingProcessQueueTest-processThread",
epicsThreadPriorityMedium,
epicsThreadGetStackSize(
epicsThreadStackMedium),
CodecTest::blockingProcessQueueThread,
&valueHolder);
Thread thr(Thread::Config(&valueHolder)
.name("testBlockingProcessQueueTest-processThread"));
epicsThreadSleep(3);
testOk(_processTreadExited.get() == false,
"%s: _processTreadExited.get() == false",
CURRENT_FUNCTION);
valueHolder.waiter.wait();
// let's put something into it
codec.enqueueSendRequest(sender);
codec.enqueueSendRequest(std::tr1::shared_ptr<TransportSender>(new TransportSenderSignal(done)));
epicsThreadSleep(1);
testDiag("Waiting for work");
done.wait();
testOk((std::size_t)PVA_MESSAGE_HEADER_SIZE ==
codec._writeBuffer.getPosition(),
"%s: PVA_MESSAGE_HEADER_SIZE == "
"codec._writeBuffer.getPosition()",
CURRENT_FUNCTION);
"codec._writeBuffer.getPosition() (%u)",
CURRENT_FUNCTION,
(unsigned)codec._writeBuffer.getPosition());
codec.endBlockedProcessSendQueue();
codec.breakSender();
epicsThreadSleep(1);
testOk(_processTreadExited.get() == true,
"%s: _processTreadExited.get() == true", CURRENT_FUNCTION);
thr.exitWait();
}
private:
void static blockingProcessQueueThread(void *param) {
ValueHolder *valueHolder = static_cast<ValueHolder *>(param);
// this should block
valueHolder->_testCodec.processSendQueue();
valueHolder->_processTreadExited.getAndSet(true);
}
AtomicValue<bool> _processTreadExited;
};
}

View File

@@ -371,17 +371,6 @@ int main()
{
for (int i = 0; i < 10; i++) {
{
/*
ClientContextImpl::shared_pointer context = createClientContextImpl();
context->printInfo();
context->initialize();
context->printInfo();
epicsThreadSleep ( SLEEP_TIME );
ChannelProvider::shared_pointer provider = context->getProvider();
*/
ClientFactory::start();
ChannelProvider::shared_pointer provider = getChannelProviderRegistry()->getProvider("pva");

View File

@@ -1554,12 +1554,14 @@ public:
m_channelRPCRequester->requestDone(Status::Ok, shared_from_this(), result);
}
#ifndef TESTSERVERNOMAIN
else if (channelName.find("testServerShutdown") == 0)
{
PVStructure::shared_pointer nullPtr;
m_channelRPCRequester->requestDone(Status::Ok, shared_from_this(), nullPtr);
testServerShutdown();
}
#endif
else
{
/*
@@ -2649,6 +2651,7 @@ public:
{
if (address == "local")
{
// this is a server instance provider, address holds remote socket IP
if (channelName == "testCounter")
{
channelRequester->channelCreated(Status::Ok, m_counterChannel);
@@ -2727,44 +2730,89 @@ public:
};
static ServerContextImpl::shared_pointer ctx;
void testServer(int timeToRun)
struct TestServer : public Runnable
{
POINTER_DEFINITIONS(TestServer);
MockChannelProviderFactory::shared_pointer factory(new MockChannelProviderFactory());
registerChannelProviderFactory(factory);
static TestServer::shared_pointer ctx;
//ServerContextImpl::shared_pointer ctx = ServerContextImpl::create();
ctx = ServerContextImpl::create();
ctx->initialize(getChannelProviderRegistry());
Configuration::shared_pointer conf;
ServerContextImpl::shared_pointer context;
Event startup;
Thread runner;
MockChannelProviderFactory::shared_pointer factory;
ctx->printInfo();
ctx->run(timeToRun);
ctx->destroy();
unregisterChannelProviderFactory(factory);
structureChangedListeners.clear();
TestServer(const Configuration::shared_pointer& conf)
:conf(conf)
,runner(Thread::Config(this).name("TestServer").autostart(false))
,factory(new MockChannelProviderFactory())
{
Lock guard(structureStoreMutex);
structureStore.clear();
registerChannelProviderFactory(factory);
context = ServerContextImpl::create(conf);
context->initialize(getChannelProviderRegistry());
}
void start(bool inSameThread = false)
{
if (inSameThread)
{
context->run(conf->getPropertyAsInteger("timeToRun", 0)); // default is no timeout
}
else
{
runner.start();
startup.wait(); // wait for thread to start
}
}
ctx.reset();
unregisterChannelProviderFactory(factory);
~TestServer()
{
context->shutdown();
runner.exitWait();
context->destroy();
unregisterChannelProviderFactory(factory);
structureChangedListeners.clear();
{
Lock guard(structureStoreMutex);
structureStore.clear();
}
ctx.reset();
unregisterChannelProviderFactory(factory);
shutdownSimADCs();
}
shutdownSimADCs();
}
// Use with EPICS_PVA_SERVER_PORT==0 for dynamic port (unit-tests)
unsigned short getServerPort()
{
return context->getServerPort();
}
unsigned short getBroadcastPort()
{
return context->getBroadcastPort();
}
virtual void run()
{
startup.signal();
context->run(conf->getPropertyAsInteger("timeToRun", 0)); // default is no timeout
}
void waitForShutdown() {
context->shutdown();
}
void shutdown() {
context->shutdown();
}
};
TestServer::shared_pointer TestServer::ctx;
void testServerShutdown()
{
// NOTE: this is not thread-safe TODO
ctx->shutdown();
TestServer::ctx->shutdown();
}
#include <epicsGetopt.h>
@@ -2789,7 +2837,7 @@ int main(int argc, char *argv[])
int opt; /* getopt() current option */
bool debug = false;
bool cleanupAndReport = false;
int timeToRun = 0;
std::string timeToRun("0");
setvbuf(stdout,NULL,_IOLBF,BUFSIZ); /* Set stdout to line buffering */
@@ -2799,7 +2847,7 @@ int main(int argc, char *argv[])
usage(argv);
return 0;
case 't': /* Print usage */
timeToRun = atoi(optarg);
timeToRun = optarg;
break;
case 'd': /* Debug log level */
debug = true;
@@ -2827,7 +2875,14 @@ int main(int argc, char *argv[])
srand ( time(NULL) );
testServer(timeToRun);
TestServer::shared_pointer srv(new TestServer(ConfigurationBuilder()
.push_env()
.add("timeToRun", timeToRun)
.push_map()
.build()));
TestServer::ctx = srv;
srv->context->printInfo();
srv->start(true);
cout << "Done" << endl;

View File

@@ -22,8 +22,6 @@ testInetAddressUtils_SYS_LIBS_WIN32 += ws2_32
testHarness_SRCS += testInetAddressUtils.cpp
TESTS += testInetAddressUtils
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
#TESTPROD_HOST += loggerTest
#loggerTest_SRCS += loggerTest.cpp
#testHarness_SRCS += loggerTest.cpp
@@ -49,3 +47,7 @@ configurationTest_SRCS += configurationTest.cpp
configurationTest_SYS_LIBS_WIN32 += ws2_32
#testHarness_SRCS += configurationTest.cpp
TESTS += configurationTest
TESTPROD_HOST += testFairQueue
testFairQueue_SRCS += testFairQueue
TESTS += testFairQueue

View File

@@ -14,6 +14,7 @@
#include <epicsAssert.h>
#include <epicsExit.h>
#include <envDefs.h>
#include <epicsString.h>
#include <osiSock.h>
#include <epicsUnitTest.h>
@@ -30,7 +31,58 @@ void setenv(char * a, char * b, int c)
using namespace epics::pvAccess;
using namespace epics::pvData;
using namespace std;
static const char indata[] =
"hello = world \n"
" # oops\n"
" #dd=da\n"
" empty = \n"
" this = is a test\n\n"
;
static const char expectdata[] =
"empty = \n"
"hello = world\n"
"this = is a test\n"
;
static
void showEscaped(const char *msg, const std::string& s)
{
std::vector<char> chars(epicsStrnEscapedFromRawSize(s.c_str(), s.size())+1);
epicsStrnEscapedFromRaw(&chars[0], chars.size(), s.c_str(), s.size());
testDiag("%s: '%s", msg, &chars[0]);
}
static
void testProp()
{
Properties plist;
{
std::istringstream input(indata);
plist.load(input);
testOk1(!input.bad());
testOk1(input.eof());
}
testOk1(plist.size()==3);
testOk1(plist.getProperty("hello")=="world");
testOk1(plist.getProperty("this")=="is a test");
testOk1(!plist.hasProperty("foobar"));
{
std::ostringstream output;
plist.store(output);
std::string expect(expectdata), actual(output.str());
testOk1(!output.bad());
testOk(expect.size()==actual.size(), "%u == %u", (unsigned)expect.size(), (unsigned)actual.size());
testOk1(actual==expectdata);
showEscaped("actual", actual);
showEscaped("expect", expect);
}
}
static void showEnv(const char *name)
{
@@ -43,6 +95,25 @@ static void setEnv(const char *name, const char *val)
testDiag("%s = \"%s\"", name, getenv(name));
}
static void testBuilder()
{
Configuration::shared_pointer C(ConfigurationBuilder()
.add("TESTKEY","value1")
.push_map()
.push_env()
.add("OTHERKEY","value3")
.push_map()
.build());
testOk1(C->getPropertyAsString("key", "X")=="X");
testOk1(C->getPropertyAsString("TESTKEY", "X")=="value1");
testOk1(C->getPropertyAsString("OTHERKEY", "X")=="value3");
setEnv("TESTKEY", "value2");
setEnv("OTHERKEY","value2");
testOk1(C->getPropertyAsString("TESTKEY", "X")=="value2");
testOk1(C->getPropertyAsString("OTHERKEY", "X")=="value3");
}
static void showAddr(const osiSockAddr& addr)
{
char buf[40];
@@ -60,9 +131,9 @@ static void showAddr(const osiSockAddr& addr)
} while(0)
MAIN(configurationTest)
static
void testConfig()
{
testPlan(35);
testDiag("Default configuration");
Configuration::shared_pointer configuration(new SystemConfigurationImpl());
@@ -126,7 +197,14 @@ MAIN(configurationTest)
Configuration::shared_pointer configurationOut(configProvider->getConfiguration("conf1"));
testOk1(configurationOut.get() == configuration.get());
}
MAIN(configurationTest)
{
testPlan(49);
testProp();
testBuilder();
testConfig();
return testDone();
}

View File

@@ -0,0 +1,75 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* pvAccessCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <vector>
#include <pv/fairQueue.h>
#include <epicsUnitTest.h>
#include <testMain.h>
namespace {
struct Qnode : public epics::pvAccess::fair_queue<Qnode>::entry {
unsigned i;
Qnode(unsigned i):i(i) {}
};
} // namespace
static unsigned Ninput[] = {0,0,0,1,0,2,1,0,1,0,0};
static unsigned Nexpect[] = {0,1,2,0,1,0,1,0,0,0,0};
static
void testOrder()
{
epics::pvAccess::fair_queue<Qnode> Q;
typedef epics::pvAccess::fair_queue<Qnode>::value_type value_type;
std::vector<value_type> unique, inputs, outputs;
unique.resize(3);
unique[0].reset(new Qnode(0));
unique[1].reset(new Qnode(1));
unique[2].reset(new Qnode(2));
testDiag("Queueing");
for(unsigned i=0; i<NELEMENTS(Ninput); i++) {
testDiag("[%u] = %u", i, Ninput[i]);
Q.push_back(unique[Ninput[i]]);
}
testDiag("De-queue");
{
for(unsigned i=0; i<=NELEMENTS(Nexpect); i++) {
value_type E;
Q.pop_front_try(E);
if(!E) break;
outputs.push_back(E);
testDiag("Dequeue %u", E->i);
}
}
testOk(outputs.size()==NELEMENTS(Nexpect), "sizes match actual %u expected %u",
(unsigned)outputs.size(), (unsigned)NELEMENTS(Nexpect));
for(unsigned i=0; i<NELEMENTS(Nexpect); i++) {
if(i>=outputs.size()) {
testFail("output truncated");
continue;
}
testOk(outputs[i]->i==Nexpect[i], "[%u] %u == %u",
i, (unsigned)outputs[i]->i, Nexpect[i]);
}
}
MAIN(testFairQueue)
{
testPlan(12);
testOrder();
return testDone();
}

View File

@@ -180,8 +180,9 @@ void test_getBroadcastAddresses()
SOCKET socket = epicsSocketCreate(AF_INET, SOCK_STREAM, IPPROTO_TCP);
auto_ptr<InetAddrVector> broadcasts(getBroadcastAddresses(socket, 6678));
// at least one is expected
// at least one is expected, in case of no network connection a fallback address is returned
testOk1(static_cast<size_t>(0) < broadcasts->size());
//testDiag("getBroadcastAddresses() returned %zu entry/-ies.", broadcasts->size());
epicsSocketDestroy(socket);
// debug