static void checkArrI(const char *pv, long elen, epicsInt32 a, epicsInt32 b, epicsInt32 c, epicsInt32 d) { epicsInt32 buf[4]; epicsInt32 expect[4]; long nReq = NELEMENTS(buf), i; unsigned match; DBADDR addr; expect[0] = a; expect[1] = b; expect[2] = c; expect[3] = d; if (dbNameToAddr(pv, &addr)) testAbort("Unknown PV '%s'", pv); if (dbGet(&addr, DBR_LONG, buf, NULL, &nReq, NULL)) testAbort("Failed to get '%s'", pv); match = elen==nReq; for (i=0; i<nReq && i<elen; i++) { match &= buf[i]==expect[i]; } testOk(match, "dbGet(\"%s\") matches", pv); if (elen!=nReq) testDiag("lengths don't match %ld != %ld", elen, nReq); for (i=0; i<nReq && i<elen; i++) { if(buf[i]!=expect[i]) testDiag("[%ld] -> %d != %d", i, (int)expect[i], (int)buf[i]); } }
static void tester(void *raw) { caster_t *self = raw; epicsEventId sd; testDiag("UDP tester starts"); epicsMutexMustLock(lock); while(!self->shutdown) { epicsMutexUnlock(lock); epicsEventMustWait(cycled[1]); epicsMutexMustLock(lock); result = doCasterUDPPhase(self); cycles++; epicsEventSignal(cycled[0]); } testDiag("UDP tester stops"); sd = self->shutdownEvent; epicsMutexUnlock(lock); epicsEventSignal(sd); }
static int fl_equals_array(short type, const db_field_log *pfl1, void *p2) { for (int i = 0; i < pfl1->no_elements; i++) { switch (type) { case DBR_DOUBLE: if (((epicsFloat64*)pfl1->u.r.field)[i] != ((epicsInt32*)p2)[i]) { testDiag("at index=%d: field log has %g, should be %d", i, ((epicsFloat64*)pfl1->u.r.field)[i], ((epicsInt32*)p2)[i]); return 0; } break; case DBR_LONG: if (((epicsInt32*)pfl1->u.r.field)[i] != ((epicsInt32*)p2)[i]) { testDiag("at index=%d: field log has %d, should be %d", i, ((epicsInt32*)pfl1->u.r.field)[i], ((epicsInt32*)p2)[i]); return 0; } break; case DBR_STRING: if (strtol(&((const char*)pfl1->u.r.field)[i*MAX_STRING_SIZE], NULL, 0) != ((epicsInt32*)p2)[i]) { testDiag("at index=%d: field log has '%s', should be '%d'", i, &((const char*)pfl1->u.r.field)[i*MAX_STRING_SIZE], ((epicsInt32*)p2)[i]); return 0; } break; default: return 0; } } return 1; }
static void checkArrD(const char *pv, long elen, double a, double b, double c, double d) { double buf[4]; double expect[4]; long nReq = NELEMENTS(buf), i; unsigned match; DBADDR addr; expect[0] = a; expect[1] = b; expect[2] = c; expect[3] = d; if (dbNameToAddr(pv, &addr)) testAbort("Unknown PV '%s'", pv); if (dbGet(&addr, DBR_DOUBLE, buf, NULL, &nReq, NULL)) testAbort("Failed to get '%s'", pv); match = elen==nReq; for (i=0; i<nReq && i<elen; i++) { match &= fabs(buf[i]-expect[i])<0.01; } testOk(match, "dbGet(\"%s\") matches", pv); if (elen!=nReq) testDiag("lengths don't match %ld != %ld", elen, nReq); for (i=0; i<nReq && i<elen; i++) { if (fabs(buf[i]-expect[i])>=0.01) testDiag("[%ld] -> %f != %f", i, expect[i], buf[i]); } }
/* Starts "mcnt" jobs in a pool with initial and max * thread counts "icnt" and "mcnt". * The test ensures that all jobs run in parallel. * "cork" checks the function of pausing the run queue * with epicsThreadPoolQueueRun */ static void postjobs(size_t icnt, size_t mcnt, int cork) { size_t i; epicsThreadPool *pool; countPriv *priv=callocMustSucceed(1, sizeof(*priv), "postjobs priv alloc"); priv->guard=epicsMutexMustCreate(); priv->done=epicsEventMustCreate(epicsEventEmpty); priv->allrunning=epicsEventMustCreate(epicsEventEmpty); priv->count=mcnt; priv->job=callocMustSucceed(mcnt, sizeof(*priv->job), "postjobs job array"); testDiag("postjobs(%lu,%lu)", (unsigned long)icnt, (unsigned long)mcnt); { epicsThreadPoolConfig conf; epicsThreadPoolConfigDefaults(&conf); conf.initialThreads=icnt; conf.maxThreads=mcnt; testOk1((pool=epicsThreadPoolCreate(&conf))!=NULL); if(!pool) return; } if(cork) epicsThreadPoolControl(pool, epicsThreadPoolQueueRun, 0); for(i=0; i<mcnt; i++) { testDiag("i=%lu", (unsigned long)i); priv->job[i] = epicsJobCreate(pool, &countjob, priv); testOk1(priv->job[i]!=NULL); testOk1(epicsJobQueue(priv->job[i])==0); } if(cork) { /* no jobs should have run */ epicsMutexMustLock(priv->guard); testOk1(priv->count==mcnt); epicsMutexUnlock(priv->guard); epicsThreadPoolControl(pool, epicsThreadPoolQueueRun, 1); } testDiag("Waiting for all jobs to start"); epicsEventMustWait(priv->allrunning); testDiag("Stop all"); epicsEventSignal(priv->done); for(i=0; i<mcnt; i++) { testDiag("i=%lu", (unsigned long)i); epicsJobDestroy(priv->job[i]); } epicsThreadPoolDestroy(pool); epicsMutexDestroy(priv->guard); epicsEventDestroy(priv->allrunning); epicsEventDestroy(priv->done); free(priv->job); free(priv); }
static int checkValues(myStruct *my, char t, epicsUInt32 i, int f, double d, char *s1, char *s2, int c) { int ret = 1; int s1fail, s2fail; int s2valid = (s2 && s2[0] != '\0'); if (!my) return 0; #define CHK(A,B,FMT) if((A)!=(B)) {testDiag("Fail: " #A " (" FMT ") != " #B " (" FMT")", A, B); ret=0;} CHK(my->sent1, PATTERN, "%08x") CHK(my->sent2, PATTERN, "%08x") CHK(my->sent3, PATTERN, "%08x") CHK(my->sent4, PATTERN, "%08x") CHK(my->sent5, PATTERN, "%08x") CHK(my->sent6, PATTERN, "%08x") CHK(my->sent7, PATTERN, "%08x") CHK(my->tval, t, "%08x") CHK(my->ival, i, "%08x") CHK(my->flag, f, "%02x") CHK(my->dval, d, "%f") CHK(my->enumval, c, "%d") #undef CHK s2fail = s1fail = strcmp(s1, my->str); if (s2valid) s2fail = strcmp(s2, my->str); if (s1fail && s2fail) { if (s1fail) testDiag("Fail: my->str (%s) != s (%s)", my->str, s1); if (s2valid && s2fail) testDiag("Fail: my->str (%s) != s (%s)", my->str, s2); ret = 0; } return ret; }
// // verify that a timer can be destroyed in expire // void testExpireDestroy () { static const unsigned nTimers = 25u; expireDestroyVerify *pTimers[nTimers]; unsigned i; unsigned timerCount = 0; expireDestroyVerify::destroyCount = 0; testDiag ( "Testing timer destruction in expire()" ); epicsTimerQueueActive &queue = epicsTimerQueueActive::allocate ( true, epicsThreadPriorityMin ); for ( i = 0u; i < nTimers; i++ ) { pTimers[i] = new expireDestroyVerify ( queue ); timerCount += pTimers[i] ? 1 : 0; } testOk1 ( timerCount == nTimers ); testOk1 ( expireDestroyVerify::destroyCount == 0 ); testDiag ( "starting %d timers", nTimers ); epicsTime cur = epicsTime::getCurrent (); for ( i = 0u; i < nTimers; i++ ) { pTimers[i]->start ( cur ); } testDiag ( "waiting until all timers should have expired" ); epicsThreadSleep ( 5.0 ); testOk1 ( expireDestroyVerify::destroyCount == nTimers ); queue.release (); }
epicsShareFunc void testRestore(void) { aoRecord *rec0; waveformRecord *rec1; testDiag("test Restore"); initHookRegister(hookPass0); initHookRegister(hookPass1); testdbPrepare(); testdbReadDatabase("asTestIoc.dbd", NULL, NULL); /* since this test has device support it must appear in a * DLL for windows dynamic builds. * However, the rRDD function is in the executable, * and not accessible here. So use iocsh. * For rtems/vxworks the test harness clears * iocsh registrations, so iocsh can't work here. */ #if defined(__rtems__) || defined(vxWorks) asTestIoc_registerRecordDeviceDriver(pdbbase); #else iocshCmd("asTestIoc_registerRecordDeviceDriver(pdbbase)"); #endif testdbReadDatabase("asTest.db", NULL, NULL); rec0 = (aoRecord*)testdbRecordPtr("rec0"); rec1 = (waveformRecord*)testdbRecordPtr("rec1"); eltc(0); testIocInitOk(); eltc(1); testDiag("Post initialization"); testOk1(iran==3); testOk1(rec0->val==4); testOk1(rec1->nord==5); { double *buf = rec1->bptr; testOk(buf[0]==1, "buf[0] %f==1", buf[0]); testOk1(buf[1]==2); testOk1(buf[2]==3); testOk1(buf[3]==4); testOk1(buf[4]==5); } testIocShutdownOk(); /* recSup doesn't cleanup after itself */ free(rec1->bptr); testdbCleanup(); }
void TestPV::post(const pvd::BitSet& changed, bool notify) { testDiag("post %s %d changed '%s'", name.c_str(), (int)notify, toString(changed).c_str()); Guard G(provider->lock); channels_t::vector_type toupdate(channels.lock_vector()); FOREACH(it, end, toupdate) // channel { TestPVChannel *chan = it->get(); TestPVChannel::monitors_t::vector_type tomon(chan->monitors.lock_vector()); FOREACH(it2, end2, tomon) // monitor/subscription { TestPVMonitor *mon = it2->get(); if(!mon->running) continue; mon->overflow->pvStructurePtr->copyUnchecked(*value, changed); if(mon->free.empty()) { mon->inoverflow = true; mon->overflow->overrunBitSet->or_and(*mon->overflow->changedBitSet, changed); // oflow = prev_changed & new_changed *mon->overflow->changedBitSet |= changed; testDiag("overflow changed '%s' overrun '%s'", toString(*mon->overflow->changedBitSet).c_str(), toString(*mon->overflow->overrunBitSet).c_str()); } else { assert(!mon->inoverflow); if(mon->buffer.empty()) mon->needWakeup = true; AUTO_REF(elem, mon->free.front()); // Note: can't use 'changed' to optimize this copy since we don't know // the state of the free element elem->pvStructurePtr->copyUnchecked(*mon->overflow->pvStructurePtr); *elem->changedBitSet = changed; elem->overrunBitSet->clear(); // redundant/paranoia mon->buffer.push_back(elem); mon->free.pop_front(); testDiag("push %p changed '%s' overflow '%s'", elem.get(), toString(*elem->changedBitSet).c_str(), toString(*elem->overrunBitSet).c_str()); } if(mon->needWakeup && notify) { testDiag(" wakeup"); mon->needWakeup = false; UnGuard U(G); mon->requester->monitorEvent(*it2); } }
void testTask2(void *arg) { taskwdInsert(0, taskNotify, NULL); testDiag("Task suspending"); epicsThreadSuspendSelf(); epicsThreadSleep(1.0); testDiag("Alive again"); epicsThreadSleep(10.0); taskwdRemove(0); }
static void logClient(void* raw, const char* msg) { clientPvt *pvt = raw; size_t len; char show[46]; /* Simulate thread priority on non-realtime * OSs like Linux. This will cause the logging * thread to sleep with the buffer lock held. */ if (pvt->jam > 0) { pvt->jam = 0; epicsEventMustWait(pvt->jammer); } else if (pvt->jam < 0) { pvt->jam++; if (pvt->jam == 0) epicsEventMustWait(pvt->jammer); } len = strlen(msg); if (len > 45) { /* Only show start and end of long messages */ strncpy(show, msg, 20); show[20] = 0; strcat(show + 20, " ... "); strcat(show + 25, msg + len - 20); } else { strcpy(show, msg); } if (pvt->checkLen) if (!testOk(pvt->checkLen == len, "Received %d chars", (int) len)) { testDiag("Expected %d", (int) pvt->checkLen); if (!pvt->expect) testDiag("Message is \"%s\"", show); } if (pvt->expect) { if (!testOk(strcmp(pvt->expect, msg) == 0, "Message is \"%s\"", show)) { len = strlen(pvt->expect); if (len > 45) { testDiag("Expected \"%.20s ... %s\"", pvt->expect, pvt->expect + len - 20); } else { testDiag("Expected \"%s\"", pvt->expect); } } } pvt->count++; }
static void testAValExpr(const char* expr, double* args, double** aargs, double* expected, int length) { unsigned char rpn[255]; short err; double val; double aval[12]; epicsUInt32 amask; if (aCalcPostfix(expr, rpn, &err)) { testDiag("postfix: %s in expression '%s'", aCalcErrorStr(err), expr); return; } if (aCalcPerform(args, 12, aargs, 12, 12, &val, aval, rpn, 12, &amask)) { testDiag("calcPerform: error evaluating '%s'", expr); return; } bool pass = true; int i = 0; for (i = 0; i < length; i += 1) { if (finite(expected[i]) && finite(aval[i])) { if (fabs(expected[i] - aval[i]) > 1e-8) { pass = false; break; } } else if (isnan(expected[i]) && !isnan(aval[i])) { pass = false; break; } else if (aval[i] != expected[i]) { pass = false; break; } } if(!testOk(pass, "%s", expr)) { testDiag("Expected aval[%d]: %f, Got: %f", i, expected[i], aval[i]); } }
void spinThread(void *arg) { info *pinfo = (info *) arg; testDiag("spinThread %d starting", pinfo->threadnum); epicsThreadSleep(0.1); /* Try to align threads */ while (pinfo->rounds--) { epicsThreadSleep(spinDelay); epicsSpinLock(pinfo->spin); pinfo->counter[0]++; epicsSpinUnlock(pinfo->spin); } testDiag("spinThread %d exiting", pinfo->threadnum); epicsEventSignal(pinfo->done); }
/* Program exit func */ static void seqg_exit(SS_ID seqg_env) { # line 59 "../pvGetCancel.st" testDiag("exit"); # line 60 "../pvGetCancel.st" seq_test_done(); }
/* Program entry func */ static void G_prog_entry(SS_ID ssId, struct UserVar *pVar) { # line 14 "../pvGetAsync.st" seq_test_init(1); # line 15 "../pvGetAsync.st" testDiag("start"); }
/* Program exit func */ static void G_prog_exit(SS_ID ssId, struct UserVar *pVar) { # line 51 "../pvGetAsync.st" testDiag("exit"); # line 52 "../pvGetAsync.st" seq_test_done(); }
/* Program entry func */ static void seqg_entry(SS_ID seqg_env) { # line 16 "../pvGetCancel.st" seq_test_init(8 * 50); # line 17 "../pvGetCancel.st" testDiag("start"); }
extern "C" void mutexThread(void * arg) { info *pinfo = (info *)arg; testDiag("mutexThread %d starting", pinfo->threadnum); while (pinfo->quit--) { epicsMutexLockStatus status = epicsMutexLock(pinfo->mutex); testOk(status == epicsMutexLockOK, "mutexThread %d epicsMutexLock returned %d", pinfo->threadnum, (int)status); epicsThreadSleep(.1); epicsMutexUnlock(pinfo->mutex); epicsThreadSleep(.9); } testDiag("mutexThread %d exiting", pinfo->threadnum); return; }
static long initRec1(waveformRecord *prec) { testDiag("init_record(%s)", prec->name); testOk(prec->nord==0, "NORD %d==0", (int)prec->nord); iran |= 2; return 0; }
void TestChannelMonitorRequester::unlisten(pvd::MonitorPtr const & monitor) { testDiag("unlisten %p", monitor.get()); Guard G(lock); unlistend = true; wait.trigger(); }
/* Action function for state "zero" in state set "main" */ static void A_main_0_zero(SS_ID ssId, struct UserVar *pVar, int transNum, int *pNextState) { switch(transNum) { case 0: { } return; case 1: { # line 37 "../change.st" testOk(pVar->UserVar_main.x == 0, "state=zero, x=%d", pVar->UserVar_main.x); # line 38 "../change.st" pVar->UserVar_main.x = rand() % 10 - 5; # line 39 "../change.st" testDiag("new random x=%d", pVar->UserVar_main.x); # line 40 "../change.st" pVar->UserVar_main.n++; # line 41 "../change.st" if (pVar->UserVar_main.x > 0) { {*pNextState = 1; return;} } else # line 43 "../change.st" if (pVar->UserVar_main.x < 0) { {*pNextState = 2; return;} } } return; } }
void epicsSpinPerformance () { static const unsigned N = 10000; unsigned i; epicsSpinId spin; epicsTimeStamp begin; epicsTimeStamp end; double delay; /* Initialize spinlock */ spin = epicsSpinCreate(); if (!spin) testAbort("epicsSpinCreate() returned NULL"); /* test a single lock pair */ epicsTimeGetCurrent(&begin); for ( i = 0; i < N; i++ ) { tenLockPairsSquared(spin); } epicsTimeGetCurrent(&end); delay = epicsTimeDiffInSeconds(&end, &begin); delay /= N * 100u; /* convert to delay per lock pair */ delay *= 1e6; /* convert to micro seconds */ testDiag("lock()*1/unlock()*1 takes %f microseconds", delay); epicsSpinDestroy(spin); }
/* Action function for state "waitForActualToEqualRequested" in state set "monitorEvflagTest" */ static void seqg_action_monitorEvflagTest_0_waitForActualToEqualRequested(SS_ID seqg_env, int seqg_trn, int *seqg_pnst) { switch(seqg_trn) { case 0: { # line 47 "../monitorEvflag.st" if (seqg_var->actual != seqg_var->requested) { # line 48 "../monitorEvflag.st" testFail("requested(%d)!=actual(%d)", seqg_var->requested, seqg_var->actual); # line 49 "../monitorEvflag.st" seqg_var->seqg_vars_monitorEvflagTest.error = TRUE; } else # line 50 "../monitorEvflag.st" if (seqg_var->seqg_vars_monitorEvflagTest.cycleCount % 500 == 0) { # line 51 "../monitorEvflag.st" testDiag("passed %d cycles", seqg_var->seqg_vars_monitorEvflagTest.cycleCount); } # line 53 "../monitorEvflag.st" seqg_var->seqg_vars_monitorEvflagTest.cycleCount++; } return; case 1: { # line 57 "../monitorEvflag.st" testFail("timeout in cycle %d/%d (requested=%d, actual=%d)", seqg_var->seqg_vars_monitorEvflagTest.cycleCount + 1, (20 * 500), seqg_var->requested, seqg_var->actual); } return; } }
pvd::Status TestPVMonitor::stop() { testDiag("TestPVMonitor::stop %p", this); Guard G(channel->pv->provider->lock); running = false; return pvd::Status(); }
static void testEpicsSnprintf(void) { char exbuffer[80], buffer[80]; const int ivalue = 1234; const float fvalue = 1.23e4f; const char *svalue = "OneTwoThreeFour"; const char *format = "int %d float %8.2e string %s"; const char *expected = exbuffer; int size; int rtn, rlen; sprintf(exbuffer, format, ivalue, fvalue, svalue); rlen = strlen(expected)+1; strcpy(buffer, "AAAA"); for (size = 1; size < strlen(expected) + 5; ++size) { rtn = epicsSnprintf(buffer, size, format, ivalue, fvalue, svalue); testOk(rtn <= rlen-1, "epicsSnprintf(size=%d) = %d", size, rtn); if (rtn != rlen-1) testDiag("Return value does not indicate buffer size needed"); testOk(strncmp(buffer, expected, size - 1) == 0, "buffer = '%s'", buffer); rtn = strlen(buffer); testOk(rtn == (size < rlen ? size : rlen) - 1, "length = %d", rtn); } }
TestPVChannel::~TestPVChannel() { Guard G(pv->provider->lock); if(requester) testDiag("Warning: TestPVChannel dropped w/o destroy()"); epicsAtomicDecrSizeT(&countTestPVChannel); }
/* Action function for state "waitForActualToEqualRequested" in state set "monitorEvflagTest" */ static void A_monitorEvflagTest_0_waitForActualToEqualRequested(SS_ID ssId, struct UserVar *pVar, int transNum, int *pNextState) { switch(transNum) { case 0: { # line 47 "../monitorEvflag.st" if (pVar->actual != pVar->requested) { # line 48 "../monitorEvflag.st" testFail("requested(%d)!=actual(%d)", pVar->requested, pVar->actual); # line 49 "../monitorEvflag.st" pVar->UserVar_monitorEvflagTest.error = TRUE; } else # line 50 "../monitorEvflag.st" if (pVar->UserVar_monitorEvflagTest.cycleCount % 500 == 0) { # line 51 "../monitorEvflag.st" testDiag("passed %d cycles", pVar->UserVar_monitorEvflagTest.cycleCount); } # line 53 "../monitorEvflag.st" pVar->UserVar_monitorEvflagTest.cycleCount++; } return; case 1: { # line 57 "../monitorEvflag.st" testFail("timeout in cycle %d/%d (requested=%d, actual=%d)", pVar->UserVar_monitorEvflagTest.cycleCount + 1, (20 * 500), pVar->requested, pVar->actual); } return; } }
static long initRec0(aoRecord *prec) { DBLINK *plink = &prec->out; testDiag("init_record(%s)", prec->name); testOk(prec->val==2, "VAL %d==2 (pass0 value)", (int)prec->val); prec->val = 3; testOk(prec->val==3, "VAL %d==3", (int)prec->val); testOk1(plink->type==DB_LINK); if(plink->type==DB_LINK) testOk(strcmp(plink->value.pv_link.pvname,"rec0.SEVR")==0, "%s==rec0.SEVR (pass0 value)", plink->value.pv_link.pvname); else testFail("Wrong link type"); plink = &prec->sdis; testOk1(plink->type==DB_LINK); if(plink->type==DB_LINK) testOk(strcmp(plink->value.pv_link.pvname,"rec0.STAT")==0, "%s==rec0.STAT (pass0 value)", plink->value.pv_link.pvname); else testFail("Wrong link type"); iran |= 1; return 2; /* we set .VAL, so don't use RVAL */ }
TestPVMonitor::~TestPVMonitor() { Guard G(channel->pv->provider->lock); if(requester) testDiag("Warning: TestPVMonitor dropped w/o destroy()"); epicsAtomicDecrSizeT(&countTestPVMonitor); }
void TestChannelMonitorRequester::monitorEvent(pvd::MonitorPtr const & monitor) { testDiag("monitorEvent %p", monitor.get()); mon = monitor; eventCnt++; wait.trigger(); }