This is Unofficial EPICS BASE Doxygen Site
acctst.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE Versions 3.13.7
7 * and higher are distributed subject to a Software License Agreement found
8 * in file LICENSE that is included with this distribution.
9 \*************************************************************************/
10 
11 /*
12  * CA regression test
13  * Authors:
14  * Jeff Hill
15  * Murali Shankar - initial versions of verifyMultithreadSubscr
16  * Michael Abbott - initial versions of multiSubscrDestroyNoLateCallbackTest
17  *
18  */
19 
20 /*
21  * ANSI
22  */
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <math.h>
26 #include <float.h>
27 #include <string.h>
28 
29 /*
30  * EPICS
31  */
32 #define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
33 #include "epicsAssert.h"
34 #include "epicsMutex.h"
35 #include "epicsEvent.h"
36 #include "epicsTime.h"
37 #include "dbDefs.h"
38 #include "envDefs.h"
39 #include "caDiagnostics.h"
40 #include "cadef.h"
41 #include "fdmgr.h"
42 #include "epicsExit.h"
43 
44 typedef struct appChan {
45  char name[64];
48  unsigned char connected;
53  unsigned getCallbackCount;
54 } appChan;
55 
60 
61 static epicsTimeStamp showProgressBeginTime;
62 
63 static const double timeoutToPendIO = 1e20;
64 
65 #define verify(exp) ((exp) ? (void)0 : \
66  epicsAssert(__FILE__, __LINE__, #exp, epicsAssertAuthor))
67 
68 void showProgressBegin ( const char *pTestName, unsigned interestLevel )
69 {
70 
71  if ( interestLevel > 0 ) {
72  if ( interestLevel > 1 ) {
73  printf ( "%s ", pTestName );
74  epicsTimeGetCurrent ( & showProgressBeginTime );
75  }
76  printf ( "{" );
77  }
78  fflush ( stdout );
79 }
80 
81 void showProgressEnd ( unsigned interestLevel )
82 {
83  if ( interestLevel > 0 ) {
84  printf ( "}" );
85  if ( interestLevel > 1 ) {
86  epicsTimeStamp showProgressEndTime;
87  double delay;
88  epicsTimeGetCurrent ( & showProgressEndTime );
89  delay = epicsTimeDiffInSeconds ( &showProgressEndTime, &showProgressBeginTime );
90  printf ( " %f sec\n", delay );
91  }
92  else {
93  fflush ( stdout );
94  }
95  }
96 }
97 
98 void showProgress ( unsigned interestLevel )
99 {
100  if ( interestLevel > 0 ) {
101  printf ( "." );
102  fflush ( stdout );
103  }
104 }
105 
106 void nUpdatesTester ( struct event_handler_args args )
107 {
108  if ( args.status == ECA_NORMAL ) {
109  unsigned *pCtr = (unsigned *) args.usr;
110  ( *pCtr ) ++;
111  }
112  else {
113  printf ( "subscription update failed for \"%s\" because \"%s\"",
114  ca_name ( args.chid ), ca_message ( args.status ) );
115  }
116 }
117 
118 void monitorSubscriptionFirstUpdateTest ( const char *pName, chid chan, unsigned interestLevel )
119 {
120  int status;
121  struct dbr_ctrl_double currentVal;
122  double delta;
123  unsigned eventCount = 0u;
124  unsigned waitCount = 0u;
125  evid id;
126  chid chan2;
127 
128  showProgressBegin ( "monitorSubscriptionFirstUpdateTest", interestLevel );
129 
130  /*
131  * verify that the first event arrives (with evid)
132  * and channel connected
133  */
134  status = ca_add_event ( DBR_FLOAT,
135  chan, nUpdatesTester, &eventCount, &id );
136  SEVCHK ( status, 0 );
137  ca_flush_io ();
138  epicsThreadSleep ( 0.1 );
139  ca_poll (); /* emulate typical GUI */
140  while ( eventCount < 1 && waitCount++ < 100 ) {
141  printf ( "e" );
142  fflush ( stdout );
143  epicsThreadSleep ( 0.1 );
144  ca_poll (); /* emulate typical GUI */
145  }
146  verify ( eventCount > 0 );
147 
148  /* clear any knowledge of old gets */
149  ca_pend_io ( 1e-5 );
150 
151  /* verify that a ca_put() produces an update, but */
152  /* this may fail if there is an unusual deadband */
153  status = ca_get ( DBR_CTRL_DOUBLE, chan, &currentVal );
154  SEVCHK ( status, NULL );
155  status = ca_pend_io ( timeoutToPendIO );
156  SEVCHK ( status, NULL );
157  eventCount = 0u;
158  waitCount = 0u;
159  delta = ( currentVal.upper_ctrl_limit - currentVal.lower_ctrl_limit ) / 4.0;
160  if ( delta <= 0.0 ) {
161  delta = 100.0;
162  }
163  if ( currentVal.value + delta < currentVal.upper_ctrl_limit ) {
164  currentVal.value += delta;
165  }
166  else {
167  currentVal.value -= delta;
168  }
169  status = ca_put ( DBR_DOUBLE, chan, &currentVal.value );
170  SEVCHK ( status, NULL );
171  ca_flush_io ();
172  epicsThreadSleep ( 0.1 );
173  ca_poll (); /* emulate typical GUI */
174  while ( eventCount < 1 && waitCount++ < 100 ) {
175  printf ( "p" );
176  fflush ( stdout );
177  epicsThreadSleep ( 0.1 );
178  ca_poll (); /* emulate typical GUI */
179  }
180  verify ( eventCount > 0 );
181 
182  status = ca_clear_event ( id );
183  SEVCHK (status, 0);
184 
185  /*
186  * verify that the first event arrives (w/o evid)
187  * and when channel initially disconnected
188  */
189  eventCount = 0u;
190  waitCount = 0u;
191  status = ca_search ( pName, &chan2 );
192  SEVCHK ( status, 0 );
193  status = ca_add_event ( DBR_FLOAT, chan2,
194  nUpdatesTester, &eventCount, 0 );
195  SEVCHK ( status, 0 );
196  status = ca_pend_io ( timeoutToPendIO );
197  SEVCHK (status, 0);
198  epicsThreadSleep ( 0.1 );
199  ca_poll ();
200  while ( eventCount < 1 && waitCount++ < 100 ) {
201  printf ( "w" );
202  fflush ( stdout );
203  epicsThreadSleep ( 0.1 );
204  ca_poll (); /* emulate typical GUI */
205  }
206  verify ( eventCount > 0 );
207 
208  /* verify that a ca_put() produces an update, but */
209  /* this may fail if there is an unusual deadband */
210  status = ca_get ( DBR_CTRL_DOUBLE, chan2, &currentVal );
211  SEVCHK ( status, NULL );
212  status = ca_pend_io ( timeoutToPendIO );
213  SEVCHK ( status, NULL );
214  eventCount = 0u;
215  waitCount = 0u;
216  delta = ( currentVal.upper_ctrl_limit - currentVal.lower_ctrl_limit ) / 4.0;
217  if ( delta <= 0.0 ) {
218  delta = 100.0;
219  }
220  if ( currentVal.value + delta < currentVal.upper_ctrl_limit ) {
221  currentVal.value += delta;
222  }
223  else {
224  currentVal.value -= delta;
225  }
226  status = ca_put ( DBR_DOUBLE, chan2, &currentVal.value );
227  SEVCHK ( status, NULL );
228  ca_flush_io ();
229  epicsThreadSleep ( 0.1 );
230  ca_poll ();
231  while ( eventCount < 1 && waitCount++ < 100 ) {
232  printf ( "t" );
233  fflush ( stdout );
234  epicsThreadSleep ( 0.1 );
235  ca_poll (); /* emulate typical GUI */
236  }
237  verify ( eventCount > 0 );
238 
239  /* clean up */
240  status = ca_clear_channel ( chan2 );
241  SEVCHK ( status, 0 );
242 
243  showProgressEnd ( interestLevel );
244 }
245 
246 void ioTesterGet ( struct event_handler_args args )
247 {
248  if ( args.status == ECA_NORMAL ) {
249  unsigned *pCtr = (unsigned *) args.usr;
250  ( *pCtr ) ++;
251  }
252  else {
253  printf("get call back failed for \"%s\" because \"%s\"",
254  ca_name ( args.chid ), ca_message ( args.status ) );
255  }
256 }
257 
258 void ioTesterEvent ( struct event_handler_args args )
259 {
260  if ( args.status == ECA_NORMAL ) {
261  int status;
262  status = ca_get_callback ( DBR_STS_STRING, args.chid, ioTesterGet, args.usr );
263  SEVCHK ( status, 0 );
264  }
265  else {
266  printf ( "subscription update failed for \"%s\" because \"%s\"",
267  ca_name ( args.chid ), ca_message ( args.status ) );
268  }
269 }
270 
271 void verifyMonitorSubscriptionFlushIO ( chid chan, unsigned interestLevel )
272 {
273  int status;
274  unsigned eventCount = 0u;
275  unsigned waitCount = 0u;
276  evid id;
277 
278  showProgressBegin ( "verifyMonitorSubscriptionFlushIO", interestLevel );
279 
280  /*
281  * verify that the first event arrives
282  */
283  status = ca_add_event ( DBR_FLOAT,
284  chan, nUpdatesTester, &eventCount, &id );
285  SEVCHK (status, 0);
286  ca_flush_io ();
287  epicsThreadSleep ( 0.1 );
288  ca_poll ();
289  while ( eventCount < 1 && waitCount++ < 100 ) {
290  printf ( "-" );
291  fflush ( stdout );
292  epicsThreadSleep ( 0.1 );
293  ca_poll (); /* emulate typical GUI */
294  }
295  verify ( eventCount > 0 );
296  status = ca_clear_event ( id );
297  SEVCHK (status, 0);
298 
299  showProgressEnd ( interestLevel );
300 }
301 
303 {
304  appChan *pChan = (appChan *) ca_puser ( args.chid );
305 
306  verify ( pChan->channel == args.chid );
307  verify ( args.ar.read_access == ca_read_access ( args.chid ) );
308  verify ( args.ar.write_access == ca_write_access ( args.chid ) );
310  pChan->accessUpdateCount++;
311 }
312 
314 {
315  appChan *pChan = (appChan *) args.usr;
316 
317  verify ( pChan->channel == args.chid );
318  verify ( pChan->connected );
319  if ( args.status != ECA_NORMAL ) {
320  printf ( "getCallbackStateChange abnormal status was \"%s\"\n",
321  ca_message ( args.status ) );
322  verify ( args.status == ECA_NORMAL );
323  }
324 
326  pChan->getCallbackCount++;
327 }
328 
330 {
331  int status;
332 
333  appChan *pChan = (appChan *) ca_puser ( args.chid );
334 
335  verify ( pChan->channel == args.chid );
336 
337  if ( args.op == CA_OP_CONN_UP ) {
338  if ( pChan->accessRightsHandlerInstalled ) {
339  verify ( pChan->accessUpdateCount > 0u );
340  }
341  verify ( ! pChan->connected );
342  pChan->connected = 1;
343  status = ca_get_callback ( DBR_STS_STRING, args.chid, getCallbackStateChange, pChan );
344  SEVCHK (status, 0);
345  }
346  else if ( args.op == CA_OP_CONN_DOWN ) {
347  verify ( pChan->connected );
348  pChan->connected = 0u;
349  verify ( ! ca_read_access ( args.chid ) );
350  verify ( ! ca_write_access ( args.chid ) );
351  }
352  else {
353  verify ( 0 );
354  }
355  pChan->connectionUpdateCount++;
357 }
358 
360 {
361  struct dbr_sts_string * pdbrgs = ( struct dbr_sts_string * ) args.dbr;
362  appChan *pChan = (appChan *) args.usr;
363 
364  verify ( args.status == ECA_NORMAL );
365  verify ( pChan->channel == args.chid );
366  verify ( pChan->connected );
367  verify ( args.type == DBR_STS_STRING );
368  verify ( strlen ( pdbrgs->value ) <= MAX_STRING_SIZE );
369  pChan->subscriptionUpdateCount++;
371 }
372 
374 {
375  if ( args.status != ECA_NORMAL ) {
376  printf ( "noopSubscriptionStateChange: subscription update failed for \"%s\" because \"%s\"",
377  ca_name ( args.chid ), ca_message ( args.status ) );
378  }
379 }
380 
381 /*
382  * verifyConnectionHandlerConnect ()
383  *
384  * 1) verify that connection handler runs during connect
385  *
386  * 2) verify that access rights handler runs during connect
387  *
388  * 3) verify that get call back runs from connection handler
389  * (and that they are not required to flush in the connection handler)
390  *
391  * 4) verify that first event callback arrives after connect
392  *
393  * 5) verify subscription can be cleared before channel is cleared
394  *
395  * 6) verify subscription can be cleared by clearing the channel
396  *
397  * 7) verify that a nill access rights handler can be installed
398  */
399 void verifyConnectionHandlerConnect ( appChan *pChans, unsigned chanCount,
400  unsigned repetitionCount, unsigned interestLevel )
401 {
402  int status;
403  unsigned i, j;
404 
405  showProgressBegin ( "verifyConnectionHandlerConnect", interestLevel );
406 
407  for ( i = 0; i < repetitionCount; i++ ) {
409  accessUpdateCount = 0u;
411  getCallbackCount = 0u;
412 
413  for ( j = 0u; j < chanCount; j++ ) {
414 
415  pChans[j].subscriptionUpdateCount = 0u;
416  pChans[j].accessUpdateCount = 0u;
417  pChans[j].accessRightsHandlerInstalled = 0;
418  pChans[j].connectionUpdateCount = 0u;
419  pChans[j].getCallbackCount = 0u;
420  pChans[j].connected = 0u;
421 
422  status = ca_search_and_connect ( pChans[j].name,
423  &pChans[j].channel, connectionStateChange, &pChans[j] );
424  SEVCHK ( status, NULL );
425 
427  pChans[j].channel, accessRightsStateChange );
428  SEVCHK ( status, NULL );
429  pChans[j].accessRightsHandlerInstalled = 1;
430 
431  status = ca_add_event ( DBR_STS_STRING, pChans[j].channel,
432  subscriptionStateChange, &pChans[j], &pChans[j].subscription );
433  SEVCHK ( status, NULL );
434 
435  verify ( ca_test_io () == ECA_IODONE );
436  }
437 
438  ca_flush_io ();
439 
440  showProgress ( interestLevel );
441 
442  while ( connectionUpdateCount < chanCount ||
443  getCallbackCount < chanCount ) {
444  epicsThreadSleep ( 0.1 );
445  ca_poll (); /* emulate typical GUI */
446  }
447 
448  for ( j = 0u; j < chanCount; j++ ) {
449  verify ( pChans[j].getCallbackCount == 1u);
450  verify ( pChans[j].connectionUpdateCount > 0 );
451  if ( pChans[j].connectionUpdateCount > 1u ) {
452  printf ("Unusual connection activity count = %u on channel %s?\n",
453  pChans[j].connectionUpdateCount, pChans[j].name );
454  }
455  verify ( pChans[j].accessUpdateCount > 0 );
456  if ( pChans[j].accessUpdateCount > 1u ) {
457  printf ("Unusual access rights activity count = %u on channel %s?\n",
458  pChans[j].connectionUpdateCount, pChans[j].name );
459  }
460  }
461 
462  ca_self_test ();
463 
464  showProgress ( interestLevel );
465 
466  for ( j = 0u; j < chanCount; j += 2 ) {
467  status = ca_clear_event ( pChans[j].subscription );
468  SEVCHK ( status, NULL );
469  }
470 
471  ca_self_test ();
472 
473  showProgress ( interestLevel );
474 
475  for ( j = 0u; j < chanCount; j++ ) {
477  pChans[j].channel, 0 );
478  SEVCHK ( status, NULL );
479  }
480 
481  for ( j = 0u; j < chanCount; j++ ) {
482  status = ca_clear_channel ( pChans[j].channel );
483  SEVCHK ( status, NULL );
484  }
485 
486  ca_self_test ();
487 
488  showProgress ( interestLevel );
489 
490  }
491  showProgressEnd ( interestLevel );
492 }
493 
494 /*
495  * verifyBlockingConnect ()
496  *
497  * 1) verify that we dont print a disconnect message when
498  * we delete the last channel
499  *
500  * 2) verify that we delete the connection to the IOC
501  * when the last channel is deleted.
502  *
503  * 3) verify channel connection state variables
504  *
505  * 4) verify ca_test_io () and ca_pend_io () work with
506  * channels w/o connection handlers
507  *
508  * 5) verify that the pending IO count is properly
509  * maintained when we are add/removing a connection
510  * handler
511  *
512  * 6) verify that the pending IO count goes to zero
513  * if the channel is deleted before it connects.
514  */
515 void verifyBlockingConnect ( appChan *pChans, unsigned chanCount,
516  unsigned repetitionCount, unsigned interestLevel )
517 {
518  int status;
519  unsigned i, j;
520  unsigned connections;
521  unsigned backgroundConnCount = ca_get_ioc_connection_count ();
522 
523  showProgressBegin ( "verifyBlockingConnect", interestLevel );
524 
525  i = 0;
526  while ( backgroundConnCount > 1u ) {
527  backgroundConnCount = ca_get_ioc_connection_count ();
528  verify ( i++ < 10 );
529  printf ( "Z" );
530  fflush ( stdout );
531  epicsThreadSleep ( 1.0 );
532  }
533 
534  for ( i = 0; i < repetitionCount; i++ ) {
535 
536  for ( j = 0u; j < chanCount; j++ ) {
537  pChans[j].subscriptionUpdateCount = 0u;
538  pChans[j].accessUpdateCount = 0u;
539  pChans[j].accessRightsHandlerInstalled = 0;
540  pChans[j].connectionUpdateCount = 0u;
541  pChans[j].getCallbackCount = 0u;
542  pChans[j].connected = 0u;
543 
544  status = ca_search_and_connect ( pChans[j].name, &pChans[j].channel, NULL, &pChans[j] );
545  SEVCHK ( status, NULL );
546 
547  if ( ca_state ( pChans[j].channel ) == cs_conn ) {
548  verify ( VALID_DB_REQ ( ca_field_type ( pChans[j].channel ) ) );
549  }
550  else {
551  verify ( INVALID_DB_REQ ( ca_field_type ( pChans[j].channel ) ) );
553  }
554 
556  pChans[j].channel, accessRightsStateChange );
557  SEVCHK ( status, NULL );
558  pChans[j].accessRightsHandlerInstalled = 1;
559  }
560 
561  showProgress ( interestLevel );
562 
563  for ( j = 0u; j < chanCount; j += 2 ) {
565  SEVCHK ( status, NULL );
566  }
567 
568  for ( j = 0u; j < chanCount; j += 2 ) {
569  status = ca_change_connection_event ( pChans[j].channel, NULL );
570  SEVCHK ( status, NULL );
571  }
572 
573  for ( j = 0u; j < chanCount; j += 2 ) {
575  SEVCHK ( status, NULL );
576  }
577 
578  for ( j = 0u; j < chanCount; j += 2 ) {
579  status = ca_change_connection_event ( pChans[j].channel, NULL );
580  SEVCHK ( status, NULL );
581  }
582 
583  status = ca_pend_io ( timeoutToPendIO );
584  SEVCHK ( status, NULL );
585 
586  ca_self_test ();
587 
588  showProgress ( interestLevel );
589 
590  verify ( ca_test_io () == ECA_IODONE );
591 
592  connections = ca_get_ioc_connection_count ();
593  verify ( connections == backgroundConnCount );
594 
595  for ( j = 0u; j < chanCount; j++ ) {
596  verify ( VALID_DB_REQ ( ca_field_type ( pChans[j].channel ) ) );
597  verify ( ca_state ( pChans[j].channel ) == cs_conn );
598  SEVCHK ( ca_clear_channel ( pChans[j].channel ), NULL );
599  }
600 
601  ca_self_test ();
602 
603  ca_flush_io ();
604 
605  showProgress ( interestLevel );
606 
607  /*
608  * verify that connections to IOC's that are
609  * not in use are dropped
610  */
611  if ( ca_get_ioc_connection_count () != backgroundConnCount ) {
612  epicsThreadSleep ( 0.1 );
613  ca_poll ();
614  j=0;
615  while ( ca_get_ioc_connection_count () != backgroundConnCount ) {
616  epicsThreadSleep ( 0.1 );
617  ca_poll (); /* emulate typical GUI */
618  verify ( ++j < 100 );
619  }
620  }
621  showProgress ( interestLevel );
622  }
623 
624  for ( j = 0u; j < chanCount; j++ ) {
625  status = ca_search ( pChans[j].name, &pChans[j].channel );
626  SEVCHK ( status, NULL );
627  }
628 
629  for ( j = 0u; j < chanCount; j++ ) {
630  status = ca_clear_channel ( pChans[j].channel );
631  SEVCHK ( status, NULL );
632  }
633 
634  verify ( ca_test_io () == ECA_IODONE );
635 
636  /*
637  * verify ca_pend_io() does not see old search requests
638  * (that did not specify a connection handler)
639  */
640  status = ca_search_and_connect ( pChans[0].name, &pChans[0].channel, NULL, NULL);
641  SEVCHK ( status, NULL );
642 
643  if ( ca_state ( pChans[0].channel ) == cs_never_conn ) {
644  /* force an early timeout */
645  status = ca_pend_io ( 1e-16 );
646  if ( status == ECA_TIMEOUT ) {
647  /*
648  * we end up here if the channel isnt on the same host
649  */
650  epicsThreadSleep ( 0.1 );
651  ca_poll ();
652  if ( ca_state( pChans[0].channel ) != cs_conn ) {
653  while ( ca_state ( pChans[0].channel ) != cs_conn ) {
654  epicsThreadSleep ( 0.1 );
655  ca_poll (); /* emulate typical GUI */
656  }
657  }
658 
659  status = ca_search_and_connect ( pChans[1].name, &pChans[1].channel, NULL, NULL );
660  SEVCHK ( status, NULL );
661  status = ca_pend_io ( 1e-16 );
662  if ( status != ECA_TIMEOUT ) {
663  verify ( ca_state ( pChans[1].channel ) == cs_conn );
664  }
665  status = ca_clear_channel ( pChans[1].channel );
666  SEVCHK ( status, NULL );
667  }
668  else {
669  verify ( ca_state( pChans[0].channel ) == cs_conn );
670  }
671  }
672  status = ca_clear_channel( pChans[0].channel );
673  SEVCHK ( status, NULL );
674 
675  ca_self_test ();
676 
677  showProgressEnd ( interestLevel );
678 }
679 
680 /*
681  * 1) verify that use of NULL evid does not cause problems
682  * 2) verify clear before connect
683  */
684 void verifyClear ( appChan *pChans, unsigned interestLevel )
685 {
686  int status;
687 
688  showProgressBegin ( "verifyClear", interestLevel );
689 
690  /*
691  * verify channel clear before connect
692  */
693  status = ca_search ( pChans[0].name, &pChans[0].channel );
694  SEVCHK ( status, NULL );
695 
696  status = ca_clear_channel ( pChans[0].channel );
697  SEVCHK ( status, NULL );
698 
699  /*
700  * verify subscription clear before connect
701  * and verify that NULL evid does not cause failure
702  */
703  status = ca_search ( pChans[0].name, &pChans[0].channel );
704  SEVCHK ( status, NULL );
705 
706  SEVCHK ( status, NULL );
707  status = ca_add_event ( DBR_GR_DOUBLE,
708  pChans[0].channel, noopSubscriptionStateChange, NULL, NULL );
709  SEVCHK ( status, NULL );
710 
711  status = ca_clear_channel ( pChans[0].channel );
712  SEVCHK ( status, NULL );
713  showProgressEnd ( interestLevel );
714 }
715 
716 /*
717  * grEnumTest
718  */
719 void grEnumTest ( chid chan, unsigned interestLevel )
720 {
721  struct dbr_gr_enum ge;
722  unsigned count;
723  int status;
724  unsigned i;
725 
726  showProgressBegin ( "grEnumTest", interestLevel );
727 
728  ge.no_str = -1;
729 
730  status = ca_get (DBR_GR_ENUM, chan, &ge);
731  SEVCHK (status, "DBR_GR_ENUM ca_get()");
732 
733  status = ca_pend_io (timeoutToPendIO);
734  verify (status == ECA_NORMAL);
735 
736  verify ( ge.no_str >= 0 && ge.no_str < NELEMENTS(ge.strs) );
737  if ( ge.no_str > 0 ) {
738  printf ("Enum state str = {");
739  count = (unsigned) ge.no_str;
740  for (i=0; i<count; i++) {
741  printf ("\"%s\" ", ge.strs[i]);
742  }
743  printf ("}");
744  }
745  showProgressEnd ( interestLevel );
746 }
747 
748 /*
749  * ctrlDoubleTest
750  */
751 void ctrlDoubleTest ( chid chan, unsigned interestLevel )
752 {
753  struct dbr_ctrl_double *pCtrlDbl;
754  dbr_double_t *pDbl;
755  unsigned nElem = ca_element_count(chan);
756  double slice = 3.14159 / nElem;
757  size_t size;
758  int status;
759  unsigned i;
760 
761 
762  if (!ca_write_access(chan)) {
763  printf ("skipped ctrl dbl test - no write access\n");
764  return;
765  }
766 
768  printf ("skipped ctrl dbl test - not an analog type\n");
769  return;
770  }
771 
772  showProgressBegin ( "ctrlDoubleTest", interestLevel );
773 
774  size = sizeof (*pDbl)*ca_element_count(chan);
775  pDbl = malloc (size);
776  verify (pDbl!=NULL);
777 
778  /*
779  * initialize the array
780  */
781  for (i=0; i<nElem; i++) {
782  pDbl[i] = sin (i*slice);
783  }
784 
785  /*
786  * write the array to the PV
787  */
788  status = ca_array_put (DBR_DOUBLE,
789  ca_element_count(chan),
790  chan, pDbl);
791  SEVCHK (status, "ctrlDoubleTest, ca_array_put");
792 
794  pCtrlDbl = (struct dbr_ctrl_double *) malloc (size);
795  verify (pCtrlDbl!=NULL);
796 
797  /*
798  * read the array from the PV
799  */
800  status = ca_array_get (DBR_CTRL_DOUBLE,
801  ca_element_count(chan),
802  chan, pCtrlDbl);
803  SEVCHK (status, "ctrlDoubleTest, ca_array_get");
804  status = ca_pend_io ( timeoutToPendIO );
805  verify (status==ECA_NORMAL);
806 
807  /*
808  * verify the result
809  */
810  for (i=0; i<nElem; i++) {
811  double diff = pDbl[i] - sin (i*slice);
812  verify (fabs(diff) < DBL_EPSILON*4);
813  }
814 
815  free (pCtrlDbl);
816  free (pDbl);
817  showProgressEnd ( interestLevel );
818 }
819 
820 /*
821  * ca_pend_io() must block
822  */
823 void verifyBlockInPendIO ( chid chan, unsigned interestLevel )
824 {
825  int status;
826 
827  if ( ca_read_access (chan) ) {
828  dbr_long_t req;
829  dbr_long_t resp;
830 
831  showProgressBegin ( "verifyBlockInPendIO", interestLevel );
832  req = 0;
833  resp = -100;
834  SEVCHK ( ca_put (DBR_LONG, chan, &req), NULL );
835  SEVCHK ( ca_get (DBR_LONG, chan, &resp), NULL );
836  status = ca_pend_io (1.0e-12);
837  if ( status == ECA_NORMAL ) {
838  if ( resp != req ) {
839  printf (
840  "short tmo get block test failed - val written %d\n", req );
841  printf (
842  "short tmo tmo get block test failed - val read %d\n", resp );
843  verify ( 0 );
844  }
845  }
846  else if ( resp != -100 ) {
847  printf ( "CA didnt block for get to return?\n" );
848  }
849 
850  req = 1;
851  resp = -100;
852  SEVCHK ( ca_put (DBR_LONG, chan, &req), NULL );
853  SEVCHK ( ca_get (DBR_LONG, chan, &resp), NULL );
854  SEVCHK ( ca_pend_io (timeoutToPendIO) , NULL );
855  if ( resp != req ) {
856  printf (
857  "long tmo get block test failed - val written %d\n", req);
858  printf (
859  "long tmo get block test failed - val read %d\n", resp);
860  verify (0);
861  }
862  showProgressEnd ( interestLevel );
863  }
864  else {
865  printf ("skipped pend IO block test - no read access\n");
866  }
867 }
868 
869 /*
870  * floatTest ()
871  */
872 void floatTest ( chid chan, dbr_float_t beginValue, dbr_float_t increment,
873  dbr_float_t epsilon, unsigned iterations )
874 {
875  unsigned i;
876  dbr_float_t fval;
877  dbr_float_t fretval;
878  int status;
879 
880  fval = beginValue;
881  for ( i=0; i < iterations; i++ ) {
882  fretval = FLT_MAX;
883  status = ca_put ( DBR_FLOAT, chan, &fval );
884  SEVCHK ( status, NULL );
885  status = ca_get ( DBR_FLOAT, chan, &fretval );
886  SEVCHK ( status, NULL );
887  status = ca_pend_io ( timeoutToPendIO );
888  SEVCHK (status, NULL);
889  if ( fabs ( fval - fretval ) > epsilon ) {
890  printf ( "float test failed val written %f\n", fval );
891  printf ( "float test failed val read %f\n", fretval );
892  verify (0);
893  }
894  fval += increment;
895  }
896 }
897 
898 /*
899  * doubleTest ()
900  */
901 void doubleTest ( chid chan, dbr_double_t beginValue,
902  dbr_double_t increment, dbr_double_t epsilon,
903  unsigned iterations)
904 {
905  unsigned i;
906  dbr_double_t fval;
907  dbr_double_t fretval;
908  int status;
909 
910  fval = beginValue;
911  for ( i = 0; i < iterations; i++ ) {
912  fretval = DBL_MAX;
913  status = ca_put ( DBR_DOUBLE, chan, &fval );
914  SEVCHK ( status, NULL );
915  status = ca_get ( DBR_DOUBLE, chan, &fretval );
916  SEVCHK ( status, NULL );
917  status = ca_pend_io ( timeoutToPendIO );
918  SEVCHK ( status, NULL );
919  if ( fabs ( fval - fretval ) > epsilon ) {
920  printf ( "double test failed val written %f\n", fval );
921  printf ( "double test failed val read %f\n", fretval );
922  verify ( 0 );
923  }
924  fval += increment;
925  }
926 }
927 
928 /*
929  * Verify that we can write and then read back
930  * the same analog value
931  */
932 void verifyAnalogIO ( chid chan, int dataType, double min, double max,
933  int minExp, int maxExp, double epsilon, unsigned interestLevel )
934 {
935  int i;
936  double incr;
937  double epsil;
938  double base;
939  unsigned iter;
940 
941 
942  if ( ! ca_write_access ( chan ) ) {
943  printf ("skipped analog test - no write access\n");
944  return;
945  }
946 
947  if ( dbr_value_class[ca_field_type ( chan )] != dbr_class_float ) {
948  printf ("skipped analog test - not an analog type\n");
949  return;
950  }
951 
952  showProgressBegin ( "verifyAnalogIO", interestLevel );
953 
954  epsil = epsilon * 4.0;
955  base = min;
956  for ( i = minExp; i <= maxExp; i += maxExp / 10 ) {
957  incr = ldexp ( 0.5, i );
958  if ( fabs (incr) > max /10.0 ) {
959  iter = ( unsigned ) ( max / fabs (incr) );
960  }
961  else {
962  iter = 10u;
963  }
964  if ( dataType == DBR_FLOAT ) {
965  floatTest ( chan, (dbr_float_t) base, (dbr_float_t) incr,
966  (dbr_float_t) epsil, iter );
967  }
968  else if (dataType == DBR_DOUBLE ) {
969  doubleTest ( chan, (dbr_double_t) base, (dbr_double_t) incr,
970  (dbr_double_t) epsil, iter );
971  }
972  else {
973  verify ( 0 );
974  }
975  }
976  base = max;
977  for ( i = minExp; i <= maxExp; i += maxExp / 10 ) {
978  incr = - ldexp ( 0.5, i );
979  if ( fabs (incr) > max / 10.0 ) {
980  iter = (unsigned) ( max / fabs (incr) );
981  }
982  else {
983  iter = 10u;
984  }
985  if ( dataType == DBR_FLOAT ) {
986  floatTest ( chan, (dbr_float_t) base, (dbr_float_t) incr,
987  (dbr_float_t) epsil, iter );
988  }
989  else if (dataType == DBR_DOUBLE ) {
990  doubleTest ( chan, (dbr_double_t) base, (dbr_double_t) incr,
991  (dbr_double_t) epsil, iter );
992  }
993  else {
994  verify ( 0 );
995  }
996  }
997  base = - max;
998  for ( i = minExp; i <= maxExp; i += maxExp / 10 ) {
999  incr = ldexp ( 0.5, i );
1000  if ( fabs (incr) > max / 10.0 ) {
1001  iter = (unsigned) ( max / fabs ( incr ) );
1002  }
1003  else {
1004  iter = 10l;
1005  }
1006  if ( dataType == DBR_FLOAT ) {
1007  floatTest ( chan, (dbr_float_t) base, (dbr_float_t) incr,
1008  (dbr_float_t) epsil, iter );
1009  }
1010  else if (dataType == DBR_DOUBLE ) {
1011  doubleTest ( chan, (dbr_double_t) base, (dbr_double_t) incr,
1012  (dbr_double_t) epsil, iter );
1013  }
1014  else {
1015  verify ( 0 );
1016  }
1017  }
1018  showProgressEnd ( interestLevel );
1019 }
1020 
1021 /*
1022  * Verify that we can write and then read back
1023  * the same DBR_LONG value
1024  */
1025 void verifyLongIO ( chid chan, unsigned interestLevel )
1026 {
1027  int status;
1028 
1029  dbr_long_t iter, rdbk, incr;
1030  struct dbr_ctrl_long cl;
1031 
1032  if ( ca_write_access ( chan ) ) {
1033  return;
1034  }
1035 
1036  status = ca_get ( DBR_CTRL_LONG, chan, &cl );
1037  SEVCHK ( status, "control long fetch failed\n" );
1038  status = ca_pend_io ( timeoutToPendIO );
1039  SEVCHK ( status, "control long pend failed\n" );
1040 
1041  incr = ( cl.upper_ctrl_limit - cl.lower_ctrl_limit );
1042  if ( incr >= 1 ) {
1043  showProgressBegin ( "verifyLongIO", interestLevel );
1044  incr /= 1000;
1045  if ( incr == 0 ) {
1046  incr = 1;
1047  }
1048  for ( iter = cl.lower_ctrl_limit;
1049  iter <= cl.upper_ctrl_limit; iter+=incr ) {
1050 
1051  ca_put ( DBR_LONG, chan, &iter );
1052  ca_get ( DBR_LONG, chan, &rdbk );
1053  status = ca_pend_io ( timeoutToPendIO );
1054  SEVCHK ( status, "get pend failed\n" );
1055  verify ( iter == rdbk );
1056  }
1057  showProgressEnd ( interestLevel );
1058  }
1059  else {
1060  printf ( "strange limits configured for channel \"%s\"\n", ca_name (chan) );
1061  }
1062 }
1063 
1064 /*
1065  * Verify that we can write and then read back
1066  * the same DBR_SHORT value
1067  */
1068 void verifyShortIO ( chid chan, unsigned interestLevel )
1069 {
1070  int status;
1071 
1072  dbr_short_t iter, rdbk, incr;
1073  struct dbr_ctrl_short cl;
1074 
1075  if ( ca_write_access ( chan ) ) {
1076  return;
1077  }
1078 
1079  status = ca_get ( DBR_CTRL_SHORT, chan, &cl );
1080  SEVCHK ( status, "control short fetch failed\n" );
1081  status = ca_pend_io ( timeoutToPendIO );
1082  SEVCHK ( status, "control short pend failed\n" );
1083 
1084  incr = (dbr_short_t) ( cl.upper_ctrl_limit - cl.lower_ctrl_limit );
1085  if ( incr >= 1 ) {
1086  showProgressBegin ( "verifyShortIO", interestLevel );
1087 
1088  incr /= 1000;
1089  if ( incr == 0 ) {
1090  incr = 1;
1091  }
1092  for ( iter = (dbr_short_t) cl.lower_ctrl_limit;
1093  iter <= (dbr_short_t) cl.upper_ctrl_limit;
1094  iter = (dbr_short_t) (iter + incr) ) {
1095 
1096  ca_put ( DBR_SHORT, chan, &iter );
1097  ca_get ( DBR_SHORT, chan, &rdbk );
1098  status = ca_pend_io ( timeoutToPendIO );
1099  SEVCHK ( status, "get pend failed\n" );
1100  verify ( iter == rdbk );
1101  }
1102  showProgressEnd ( interestLevel );
1103  }
1104  else {
1105  printf ( "Strange limits configured for channel \"%s\"\n", ca_name (chan) );
1106  }
1107 }
1108 
1109 void verifyHighThroughputRead ( chid chan, unsigned interestLevel )
1110 {
1111  int status;
1112  unsigned i;
1113 
1114  /*
1115  * verify we dont jam up on many uninterrupted
1116  * solicitations
1117  */
1118  if ( ca_read_access (chan) ) {
1119  dbr_float_t temp;
1120  showProgressBegin ( "verifyHighThroughputRead", interestLevel );
1121  for ( i=0; i<10000; i++ ) {
1122  status = ca_get ( DBR_FLOAT, chan, &temp );
1123  SEVCHK ( status ,NULL );
1124  }
1125  status = ca_pend_io ( timeoutToPendIO );
1126  SEVCHK ( status, NULL );
1127  showProgressEnd ( interestLevel );
1128  }
1129  else {
1130  printf ( "Skipped highthroughput read test - no read access\n" );
1131  }
1132 }
1133 
1134 void verifyHighThroughputWrite ( chid chan, unsigned interestLevel )
1135 {
1136  int status;
1137  unsigned i;
1138 
1139  if (ca_write_access ( chan ) ) {
1140  showProgressBegin ( "verifyHighThroughputWrite", interestLevel );
1141  for ( i=0; i<10000; i++ ) {
1142  dbr_double_t fval = 3.3;
1143  status = ca_put ( DBR_DOUBLE, chan, &fval );
1144  SEVCHK ( status, NULL );
1145  }
1146  SEVCHK ( ca_pend_io (timeoutToPendIO), NULL );
1147  showProgressEnd ( interestLevel );
1148  }
1149  else{
1150  printf("Skipped multiple put test - no write access\n");
1151  }
1152 }
1153 
1154 /*
1155  * verify we dont jam up on many uninterrupted
1156  * get callback requests
1157  */
1158 void verifyHighThroughputReadCallback ( chid chan, unsigned interestLevel )
1159 {
1160  unsigned i;
1161  int status;
1162 
1163  if ( ca_read_access ( chan ) ) {
1164  unsigned count = 0u;
1165  showProgressBegin ( "verifyHighThroughputReadCallback", interestLevel );
1166  for ( i=0; i<10000; i++ ) {
1167  status = ca_array_get_callback (
1168  DBR_FLOAT, 1, chan, nUpdatesTester, &count );
1169  SEVCHK ( status, NULL );
1170  }
1171  SEVCHK ( ca_flush_io (), NULL );
1172  while ( count < 10000u ) {
1173  epicsThreadSleep ( 0.1 );
1174  ca_poll (); /* emulate typical GUI */
1175  }
1176  showProgressEnd ( interestLevel );
1177  }
1178  else {
1179  printf ( "Skipped multiple get cb test - no read access\n" );
1180  }
1181 }
1182 
1183 /*
1184  * verify we dont jam up on many uninterrupted
1185  * put callback request
1186  */
1187 void verifyHighThroughputWriteCallback ( chid chan, unsigned interestLevel )
1188 {
1189  unsigned i;
1190  int status;
1191 
1192  if ( ca_write_access (chan) && ca_v42_ok (chan) ) {
1193  unsigned count = 0u;
1194  dbr_double_t dval;
1195  showProgressBegin ( "verifyHighThroughputWriteCallback", interestLevel );
1196  for ( i=0; i<10000; i++ ) {
1197  dval = i + 1;
1198  status = ca_array_put_callback (
1199  DBR_DOUBLE, 1, chan, &dval,
1200  nUpdatesTester, &count );
1201  SEVCHK ( status, NULL );
1202  }
1203  SEVCHK ( ca_flush_io (), NULL );
1204  dval = 0.0;
1205  status = ca_get ( DBR_DOUBLE, chan, &dval );
1206  SEVCHK ( status,
1207  "verifyHighThroughputWriteCallback, verification get" );
1208  status = ca_pend_io ( timeoutToPendIO );
1209  SEVCHK ( status,
1210  "verifyHighThroughputWriteCallback, verification get pend" );
1211  verify ( dval == i );
1212  showProgressEnd ( interestLevel );
1213  }
1214  else {
1215  printf ( "Skipped multiple put cb test - no write access\n" );
1216  }
1217 }
1218 
1219 void verifyBadString ( chid chan, unsigned interestLevel )
1220 {
1221  int status;
1222 
1223  /*
1224  * verify that we detect that a large string has been written
1225  */
1226  if ( ca_write_access (chan) ) {
1227  dbr_string_t stimStr;
1228  dbr_string_t respStr;
1229  showProgressBegin ( "verifyBadString", interestLevel );
1230  memset (stimStr, 'a', sizeof (stimStr) );
1231  status = ca_array_put ( DBR_STRING, 1u, chan, stimStr );
1232  verify ( status != ECA_NORMAL );
1233  sprintf ( stimStr, "%u", 8u );
1234  status = ca_array_put ( DBR_STRING, 1u, chan, stimStr );
1235  verify ( status == ECA_NORMAL );
1236  status = ca_array_get ( DBR_STRING, 1u, chan, respStr );
1237  verify ( status == ECA_NORMAL );
1238  status = ca_pend_io ( timeoutToPendIO );
1239  verify ( status == ECA_NORMAL );
1240  if ( strcmp ( stimStr, respStr ) ) {
1241  printf (
1242  "Test fails if stim \"%s\" isnt roughly equiv to resp \"%s\"\n",
1243  stimStr, respStr);
1244  }
1245  showProgressEnd ( interestLevel );
1246  }
1247  else {
1248  printf ( "Skipped bad string test - no write access\n" );
1249  }
1250 }
1251 
1252 /*
1253  * multiple_sg_requests()
1254  */
1256 {
1257  int status;
1258  unsigned i;
1259  static dbr_float_t fvalput = 3.3F;
1260  static dbr_float_t fvalget;
1261 
1262  for ( i=0; i < 1000; i++ ) {
1263  if ( ca_write_access (chix) ){
1264  status = ca_sg_array_put ( gid, DBR_FLOAT, 1,
1265  chix, &fvalput);
1266  SEVCHK ( status, NULL );
1267  }
1268 
1269  if ( ca_read_access (chix) ) {
1270  status = ca_sg_array_get ( gid, DBR_FLOAT, 1,
1271  chix, &fvalget);
1272  SEVCHK ( status, NULL );
1273  }
1274  }
1275 }
1276 
1277 /*
1278  * test_sync_groups()
1279  */
1280 void test_sync_groups ( chid chan, unsigned interestLevel )
1281 {
1282  int status;
1283  CA_SYNC_GID gid1=0;
1284  CA_SYNC_GID gid2=0;
1285 
1286  if ( ! ca_v42_ok ( chan ) ) {
1287  printf ( "skipping sync group test - server is on wrong version\n" );
1288  }
1289 
1290  showProgressBegin ( "test_sync_groups", interestLevel );
1291 
1292  status = ca_sg_create ( &gid1 );
1293  SEVCHK ( status, NULL );
1294 
1295  multiple_sg_requests ( chan, gid1 );
1296  status = ca_sg_reset ( gid1 );
1297  SEVCHK ( status, NULL );
1298 
1299  status = ca_sg_create ( &gid2 );
1300  SEVCHK ( status, NULL );
1301 
1302  multiple_sg_requests ( chan, gid2 );
1303  multiple_sg_requests ( chan, gid1 );
1304  status = ca_sg_test ( gid2 );
1305  SEVCHK ( status, "SYNC GRP2" );
1306  status = ca_sg_test ( gid1 );
1307  SEVCHK ( status, "SYNC GRP1" );
1308  status = ca_sg_block ( gid1, 500.0 );
1309  SEVCHK ( status, "SYNC GRP1" );
1310  status = ca_sg_block ( gid2, 500.0 );
1311  SEVCHK ( status, "SYNC GRP2" );
1312 
1313  status = ca_sg_delete ( gid2 );
1314  SEVCHK (status, NULL);
1315  status = ca_sg_create ( &gid2 );
1316  SEVCHK (status, NULL);
1317 
1318  multiple_sg_requests ( chan, gid1 );
1319  multiple_sg_requests ( chan, gid2 );
1320  status = ca_sg_block ( gid1, 500.0 );
1321  SEVCHK ( status, "SYNC GRP1" );
1322  status = ca_sg_block ( gid2, 500.0 );
1323  SEVCHK ( status, "SYNC GRP2" );
1324  status = ca_sg_delete ( gid1 );
1325  SEVCHK ( status, NULL );
1326  status = ca_sg_delete ( gid2 );
1327  SEVCHK ( status, NULL );
1328 
1329  showProgressEnd ( interestLevel );
1330 }
1331 
1332 #define multiSubscrDestroyNoLateCallbackEventCount 500
1333 
1336  size_t m_nCallback;
1339 };
1340 
1342  const char * m_pChanName;
1349 };
1350 
1351 static void noLateCallbackDetect ( struct event_handler_args args )
1352 {
1353  int callbackIsOk;
1354  struct MultiSubscrDestroyNoLateCallbackEventData * const pEventData = args.usr;
1355  epicsMutexLockStatus lockStatus = epicsMutexLock ( pEventData->m_pTestData->m_mutex );
1356  callbackIsOk = pEventData->m_callbackIsOk;
1357  pEventData->m_nCallback++;
1358  epicsMutexUnlock ( pEventData->m_pTestData->m_mutex );
1359  verify ( lockStatus == epicsMutexLockOK );
1360  verify ( callbackIsOk );
1361 }
1362 
1363 static void multiSubscrDestroyNoLateCallbackThread ( void * pParm )
1364 {
1365  struct MultiSubscrDestroyNoLateCallbackTestData * const pTestData =
1366  ( struct MultiSubscrDestroyNoLateCallbackTestData * ) pParm;
1367  unsigned i, j;
1368  int status;
1369 
1371  verify ( status == ECA_NORMAL );
1372 
1373  status = ca_create_channel ( pTestData->m_pChanName, 0, 0,
1374  CA_PRIORITY_DEFAULT, &pTestData->m_chan );
1375  status = ca_pend_io ( timeoutToPendIO );
1376  SEVCHK ( status, "multiSubscrDestroyLateNoCallbackTest: channel connect failed" );
1377  verify ( status == ECA_NORMAL );
1378 
1379  /*
1380  * create a set of subscriptions
1381  */
1382  for ( i=0; i < 10000; i++ ) {
1383  unsigned int priorityOfTestThread;
1384  for ( j=0; j < multiSubscrDestroyNoLateCallbackEventCount; j++ ) {
1385  epicsMutexLockStatus lockStatus = epicsMutexLock ( pTestData->m_mutex );
1386  verify ( lockStatus == epicsMutexLockOK );
1387  pTestData->m_eventData[j].m_nCallback = 0;
1388  pTestData->m_eventData[j].m_callbackIsOk = TRUE;
1389  pTestData->m_eventData[j].m_pTestData = pTestData;
1390  epicsMutexUnlock ( pTestData->m_mutex );
1391  SEVCHK ( ca_add_event ( DBR_GR_FLOAT, pTestData->m_chan, noLateCallbackDetect,
1392  &pTestData->m_eventData[j], &pTestData->m_eventData[j].m_id ) , NULL );
1393  }
1394  SEVCHK ( ca_flush_io(), NULL );
1395 
1396  /*
1397  * raise the priority of the current thread hoping to improve our
1398  * likelyhood of detecting a bug
1399  */
1400  priorityOfTestThread = epicsThreadGetPrioritySelf ();
1402 
1403 
1404  /*
1405  * wait for the first subscription update to arrive
1406  */
1407  {
1408  epicsMutexLockStatus lockStatus = epicsMutexLock ( pTestData->m_mutex );
1409  verify ( lockStatus == epicsMutexLockOK );
1410  while ( pTestData->m_eventData[0].m_nCallback == 0 ) {
1411  epicsMutexUnlock ( pTestData->m_mutex );
1412  epicsThreadSleep ( 50e-6 );
1413  lockStatus = epicsMutexLock ( pTestData->m_mutex );
1414  verify ( lockStatus == epicsMutexLockOK );
1415  }
1416  epicsMutexUnlock ( pTestData->m_mutex );
1417  }
1418  /*
1419  * try to destroy all of the subscriptions at precisely the same time that
1420  * their first callbacks are running
1421  */
1422  for ( j=0; j < multiSubscrDestroyNoLateCallbackEventCount; j++ ) {
1423  epicsMutexLockStatus lockStatus;
1424  SEVCHK ( ca_clear_event ( pTestData->m_eventData[j].m_id ) , NULL );
1425  lockStatus = epicsMutexLock ( pTestData->m_mutex );
1426  verify ( lockStatus == epicsMutexLockOK );
1427  pTestData->m_eventData[j].m_callbackIsOk = FALSE;
1428  epicsMutexUnlock ( pTestData->m_mutex );
1429  }
1430  /*
1431  * return to the original priority
1432  */
1433  epicsThreadSetPriority ( epicsThreadGetIdSelf(), priorityOfTestThread );
1434 
1435  if ( i % 1000 == 0 ) {
1436  showProgress ( pTestData->m_interestLevel );
1437  }
1438  }
1439 
1440  SEVCHK ( ca_clear_channel ( pTestData->m_chan ), NULL );
1441 
1442  ca_context_destroy ();
1443 
1444  epicsEventMustTrigger ( pTestData->m_testDoneEvent );
1445 }
1446 
1447 /*
1448  * verify that, in a preemtive callback mode client, a subscription callback never
1449  * comes after the subscription is destroyed
1450  */
1451 static void multiSubscrDestroyNoLateCallbackTest ( const char *pName, unsigned interestLevel )
1452 {
1453  struct MultiSubscrDestroyNoLateCallbackTestData * pTestData;
1454 
1455  showProgressBegin ( "multiSubscrDestroyNoLateCallbackTest", interestLevel );
1456 
1457  pTestData = calloc ( 1u, sizeof ( struct MultiSubscrDestroyNoLateCallbackTestData ) );
1458  verify ( pTestData );
1459  pTestData->m_mutex = epicsMutexMustCreate ();
1461  pTestData->m_pChanName = pName;
1462  pTestData->m_interestLevel = interestLevel;
1464  "multiSubscrDestroyNoLateCallbackTest",
1467  multiSubscrDestroyNoLateCallbackThread,
1468  pTestData );
1469 
1470  /*
1471  * wait for test to complete
1472  */
1473  epicsEventMustWait ( pTestData->m_testDoneEvent );
1474 
1475  /*
1476  * cleanup
1477  */
1478  epicsMutexDestroy ( pTestData->m_mutex );
1479  epicsEventDestroy ( pTestData->m_testDoneEvent );
1480  free ( pTestData );
1481 
1482  showProgressEnd ( interestLevel );
1483 }
1484 
1485 /*
1486  * multiSubscriptionDeleteTest
1487  *
1488  * 1) verify we can add many monitors at once
1489  * 2) verify that under heavy load the last monitor
1490  * returned is the last modification sent
1491  * 3) attempt to delete monitors while many monitors
1492  * are running
1493  */
1494 void multiSubscriptionDeleteTest ( chid chan, unsigned interestLevel )
1495 {
1496  unsigned count = 0u;
1497  evid mid[1000];
1498  dbr_float_t temp, getResp;
1499  unsigned i;
1500 
1501  showProgressBegin ( "multiSubscriptionDeleteTest", interestLevel );
1502 
1503  for ( i=0; i < NELEMENTS (mid); i++ ) {
1505  &count, &mid[i]) , NULL );
1506  }
1507 
1508  /*
1509  * force all of the monitors subscription requests to
1510  * complete
1511  *
1512  * NOTE: this hopefully demonstrates that when the
1513  * server is very busy with monitors the client
1514  * is still able to punch through with a request.
1515  */
1516  SEVCHK ( ca_get ( DBR_FLOAT,chan,&getResp ), NULL );
1517  SEVCHK ( ca_pend_io ( timeoutToPendIO ), NULL );
1518 
1519  showProgress ( interestLevel );
1520 
1521  /*
1522  * attempt to generate heavy event traffic before initiating
1523  * the monitor delete
1524  */
1525  if ( ca_write_access (chan) ) {
1526  for ( i=0; i < NELEMENTS (mid); i++ ) {
1527  temp = (float) i;
1528  SEVCHK ( ca_put (DBR_FLOAT, chan, &temp), NULL);
1529  }
1530  }
1531 
1532  showProgress ( interestLevel );
1533 
1534  /*
1535  * without pausing begin deleting the event subscriptions
1536  * while the queue is full
1537  *
1538  * continue attempting to generate heavy event traffic
1539  * while deleting subscriptions with the hope that we will
1540  * deleting an event at the instant that its callback is
1541  * occurring
1542  */
1543  for ( i=0; i < NELEMENTS (mid); i++ ) {
1544  if ( ca_write_access (chan) ) {
1545  temp = (float) i;
1546  SEVCHK ( ca_put (DBR_FLOAT, chan, &temp), NULL);
1547  }
1548  SEVCHK ( ca_clear_event ( mid[i]), NULL );
1549  }
1550 
1551  showProgress ( interestLevel );
1552 
1553  /*
1554  * force all of the clear event requests to complete
1555  */
1556  SEVCHK ( ca_get (DBR_FLOAT,chan,&temp), NULL );
1557  SEVCHK ( ca_pend_io (timeoutToPendIO), NULL );
1558 
1559  showProgressEnd ( interestLevel );
1560 }
1561 
1562 
1563 /*
1564  * singleSubscriptionDeleteTest
1565  *
1566  * verify that we dont fail when we repeatedly create
1567  * and delete only one subscription with a high level of
1568  * traffic on it
1569  */
1570 void singleSubscriptionDeleteTest ( chid chan, unsigned interestLevel )
1571 {
1572  unsigned count = 0u;
1573  evid sid;
1574  dbr_float_t temp, getResp;
1575  unsigned i;
1576 
1577  showProgressBegin ( "singleSubscriptionDeleteTest", interestLevel );
1578 
1579  for ( i=0; i < 1000; i++ ){
1580  count = 0u;
1582  &count, &sid) , NULL );
1583 
1584  if ( i % 100 == 0 ) {
1585  showProgress ( interestLevel );
1586  }
1587 
1588  /*
1589  * force the subscription request to complete
1590  */
1591  SEVCHK ( ca_get ( DBR_FLOAT, chan, &getResp ), NULL );
1592  SEVCHK ( ca_pend_io ( timeoutToPendIO ), NULL );
1593 
1594  /*
1595  * attempt to generate heavy event traffic before initiating
1596  * the monitor delete
1597  *
1598  * try to interrupt the recv thread while it is processing
1599  * incoming subscription updates
1600  */
1601  if ( ca_write_access (chan) ) {
1602  unsigned j = 0;
1603  while ( j < i ) {
1604  temp = (float) j++;
1605  SEVCHK ( ca_put (DBR_FLOAT, chan, &temp),
1606  "singleSubscriptionDeleteTest - one of multiple puts" );
1607  }
1608  ca_flush_io ();
1609  }
1610 
1611  SEVCHK ( ca_clear_event ( sid ), NULL );
1612  }
1613 
1614  showProgressEnd ( interestLevel );
1615 }
1616 
1617 /*
1618  * channelClearWithEventTrafficTest
1619  *
1620  * verify that we can delete a channel that has subcriptions
1621  * attached with heavy update traffic
1622  */
1623 void channelClearWithEventTrafficTest ( const char *pName, unsigned interestLevel )
1624 {
1625  unsigned count = 0u;
1626  evid sid;
1627  dbr_float_t temp, getResp;
1628  unsigned i;
1629 
1630  showProgressBegin ( "channelClearWithEventTrafficTest", interestLevel );
1631 
1632  for ( i=0; i < 1000; i++ ) {
1633  chid chan;
1634 
1635  int status = ca_create_channel ( pName, 0, 0,
1636  CA_PRIORITY_DEFAULT, &chan );
1637  status = ca_pend_io ( timeoutToPendIO );
1638  SEVCHK ( status, "channelClearWithEventTrafficTest: channel connect failed" );
1639  verify ( status == ECA_NORMAL );
1640 
1641  count = 0u;
1643  &count, &sid ) , NULL );
1644 
1645  /*
1646  * force the subscription request to complete
1647  */
1648  SEVCHK ( ca_get ( DBR_FLOAT, chan, &getResp ), NULL );
1649  SEVCHK ( ca_pend_io ( timeoutToPendIO ), NULL );
1650 
1651  /*
1652  * attempt to generate heavy event traffic before initiating
1653  * the channel delete
1654  *
1655  * try to interrupt the recv thread while it is processing
1656  * incoming subscription updates
1657  */
1658  if ( ca_write_access (chan) ) {
1659  unsigned j = 0;
1660  while ( j < i ) {
1661  temp = (float) j++;
1662  SEVCHK ( ca_put (DBR_FLOAT, chan, &temp), NULL);
1663  }
1664  ca_flush_io ();
1665  epicsThreadSleep ( 0.001 );
1666  }
1667 
1668  SEVCHK ( ca_clear_channel ( chan ), NULL );
1669  }
1670 
1671  showProgressEnd ( interestLevel );
1672 }
1673 
1674 
1675 
1677 
1679 {
1680  int status;
1681  status = ca_clear_event ( globalEventID );
1682  verify ( status == ECA_NORMAL );
1683 }
1684 
1685 void eventClearTest ( chid chan )
1686 {
1687  int status;
1688  evid monix1, monix2, monix3;
1689 
1691  NULL, &monix1 );
1692  SEVCHK ( status, NULL );
1693 
1694  status = ca_clear_event ( monix1 );
1695  SEVCHK ( status, NULL );
1696 
1698  NULL, &monix1 );
1699  SEVCHK ( status, NULL );
1700 
1702  NULL, &monix2);
1703  SEVCHK (status, NULL);
1704 
1705  status = ca_clear_event ( monix2 );
1706  SEVCHK ( status, NULL);
1707 
1709  NULL, &monix2);
1710  SEVCHK ( status, NULL );
1711 
1713  NULL, &monix3);
1714  SEVCHK ( status, NULL );
1715 
1716  status = ca_clear_event ( monix2 );
1717  SEVCHK ( status, NULL);
1718 
1719  status = ca_clear_event ( monix1 );
1720  SEVCHK ( status, NULL);
1721 
1722  status = ca_clear_event ( monix3 );
1723  SEVCHK ( status, NULL);
1724 
1725  status = ca_add_event ( DBR_FLOAT, chan, selfDeleteEvent,
1726  0, &globalEventID );
1727  SEVCHK ( status, NULL );
1728 }
1729 
1730 unsigned acctstExceptionCount = 0u;
1732 {
1733  acctstExceptionCount++;
1734 }
1735 
1736 static unsigned arrayEventExceptionNotifyComplete = 0;
1738 {
1739  if ( args.status == ECA_NORMAL ) {
1740  printf (
1741  "arrayEventExceptionNotify: expected "
1742  "exception but didnt receive one against \"%s\" \n",
1743  ca_name ( args.chid ) );
1744  }
1745  else {
1746  arrayEventExceptionNotifyComplete = 1;
1747  }
1748 }
1749 
1750 void exceptionTest ( chid chan, unsigned interestLevel )
1751 {
1752  int status;
1753 
1754  showProgressBegin ( "exceptionTest", interestLevel );
1755 
1756  /*
1757  * force a get exception to occur
1758  */
1759  {
1760  dbr_put_ackt_t *pRS;
1761 
1762  acctstExceptionCount = 0u;
1764  SEVCHK ( status, "exception notify install failed" );
1765 
1766  pRS = malloc ( ca_element_count (chan) * sizeof (*pRS) );
1767  verify ( pRS );
1768  status = ca_array_get ( DBR_PUT_ACKT,
1769  ca_element_count (chan), chan, pRS );
1770  SEVCHK ( status, "array read request failed" );
1771  ca_pend_io ( 1e-5 );
1772  epicsThreadSleep ( 0.1 );
1773  ca_poll ();
1774  while ( acctstExceptionCount < 1u ) {
1775  printf ( "G" );
1776  fflush ( stdout );
1777  epicsThreadSleep ( 0.1 );
1778  ca_poll (); /* emulate typical GUI */
1779  }
1780  status = ca_add_exception_event ( 0, 0 );
1781  SEVCHK ( status, "exception notify install failed" );
1782  free ( pRS );
1783  }
1784 
1785  /*
1786  * force a get call back exception to occur
1787  */
1788  {
1789  arrayEventExceptionNotifyComplete = 0u;
1791  ca_element_count (chan), chan, arrayEventExceptionNotify, 0 );
1792  if ( status != ECA_NORMAL ) {
1793  verify ( status == ECA_BADTYPE || status == ECA_GETFAIL );
1794  arrayEventExceptionNotifyComplete = 1;
1795  }
1796  ca_flush_io ();
1797  epicsThreadSleep ( 0.1 );
1798  ca_poll ();
1799  while ( ! arrayEventExceptionNotifyComplete ) {
1800  printf ( "GCB" );
1801  fflush ( stdout );
1802  epicsThreadSleep ( 0.1 );
1803  ca_poll (); /* emulate typical GUI */
1804  }
1805  }
1806 
1807  /*
1808  * force a subscription exception to occur
1809  */
1810  {
1811  evid id;
1812 
1813  arrayEventExceptionNotifyComplete = 0u;
1814  status = ca_add_array_event ( DBR_PUT_ACKT, ca_element_count ( chan ),
1815  chan, arrayEventExceptionNotify, 0, 0.0, 0.0, 0.0, &id );
1816  if ( status != ECA_NORMAL ) {
1817  verify ( status == ECA_BADTYPE || status == ECA_GETFAIL );
1818  arrayEventExceptionNotifyComplete = 1;
1819  }
1820  ca_flush_io ();
1821  epicsThreadSleep ( 0.1 );
1822  ca_poll ();
1823  while ( ! arrayEventExceptionNotifyComplete ) {
1824  printf ( "S" );
1825  fflush ( stdout );
1826  epicsThreadSleep ( 0.1 );
1827  ca_poll (); /* emulate typical GUI */
1828  }
1829  status = ca_clear_event ( id );
1830  SEVCHK ( status, "subscription clear failed" );
1831  }
1832 
1833  /*
1834  * force a put exception to occur
1835  */
1836  {
1837  dbr_string_t * pWS;
1838  unsigned i;
1839 
1840  acctstExceptionCount = 0u;
1842  SEVCHK ( status, "exception notify install failed" );
1843 
1844  pWS = malloc ( ca_element_count (chan) * MAX_STRING_SIZE );
1845  verify ( pWS );
1846  for ( i = 0; i < ca_element_count (chan); i++ ) {
1847  strcpy ( pWS[i], "@#$%" );
1848  }
1849  status = ca_array_put ( DBR_STRING,
1850  ca_element_count (chan), chan, pWS );
1851  if ( status != ECA_NORMAL ) {
1852  verify ( status == ECA_BADTYPE || status == ECA_PUTFAIL );
1853  acctstExceptionCount++; /* local PV case */
1854  }
1855  ca_flush_io ();
1856  epicsThreadSleep ( 0.1 );
1857  ca_poll ();
1858  while ( acctstExceptionCount < 1u ) {
1859  printf ( "P" );
1860  fflush ( stdout );
1861  epicsThreadSleep ( 0.1 );
1862  ca_poll (); /* emulate typical GUI */
1863  }
1864  status = ca_add_exception_event ( 0, 0 );
1865  SEVCHK ( status, "exception notify install failed" );
1866  free ( pWS );
1867  }
1868 
1869  /*
1870  * force a put callback exception to occur
1871  */
1872  {
1873  dbr_string_t *pWS;
1874  unsigned i;
1875 
1876  pWS = malloc ( ca_element_count (chan) * MAX_STRING_SIZE );
1877  verify ( pWS );
1878  for ( i = 0; i < ca_element_count (chan); i++ ) {
1879  strcpy ( pWS[i], "@#$%" );
1880  }
1881  arrayEventExceptionNotifyComplete = 0u;
1882  status = ca_array_put_callback ( DBR_STRING,
1883  ca_element_count (chan), chan, pWS,
1885  if ( status != ECA_NORMAL ) {
1886  arrayEventExceptionNotifyComplete = 1;
1887  }
1888  ca_flush_io ();
1889  epicsThreadSleep ( 0.1 );
1890  ca_poll ();
1891  while ( ! arrayEventExceptionNotifyComplete ) {
1892  printf ( "PCB" );
1893  fflush ( stdout );
1894  epicsThreadSleep ( 0.1 );
1895  ca_poll (); /* emulate typical GUI */
1896  }
1897  free ( pWS );
1898  }
1899 
1900  showProgressEnd ( interestLevel );
1901 }
1902 
1903 /*
1904  * array test
1905  *
1906  * verify that we can at least write and read back the same array
1907  * if multiple elements are present
1908  */
1909 static unsigned arrayReadNotifyComplete = 0;
1910 static unsigned arrayWriteNotifyComplete = 0;
1912 {
1913  dbr_double_t *pWF = ( dbr_double_t * ) ( args.usr );
1914  dbr_double_t *pRF = ( dbr_double_t * ) ( args.dbr );
1915  int i;
1916  for ( i = 0; i < args.count; i++ ) {
1917  verify ( pWF[i] == pRF[i] );
1918  }
1919  arrayReadNotifyComplete = 1;
1920 }
1922 {
1923  if ( args.status == ECA_NORMAL ) {
1924  arrayWriteNotifyComplete = 1;
1925  }
1926  else {
1927  printf ( "arrayWriteNotify: update failed for \"%s\" because \"%s\"",
1928  ca_name ( args.chid ), ca_message ( args.status ) );
1929  }
1930 }
1931 
1932 void arrayTest ( chid chan, unsigned maxArrayBytes, unsigned interestLevel )
1933 {
1934  dbr_double_t *pRF, *pWF;
1935  unsigned i;
1936  int status;
1937  evid id;
1938 
1939  if ( ! ca_write_access ( chan ) ) {
1940  printf ( "skipping array test - no write access\n" );
1941  return;
1942  }
1943 
1944  showProgressBegin ( "arrayTest", interestLevel );
1945 
1946  pRF = (dbr_double_t *) calloc ( ca_element_count (chan), sizeof (*pRF) );
1947  verify ( pRF != NULL );
1948 
1949  pWF = (dbr_double_t *) calloc ( ca_element_count (chan), sizeof (*pWF) );
1950  verify ( pWF != NULL );
1951 
1952  /*
1953  * write some random numbers into the array
1954  */
1955  for ( i = 0; i < ca_element_count (chan); i++ ) {
1956  pWF[i] = rand ();
1957  pRF[i] = - pWF[i];
1958  }
1959  status = ca_array_put ( DBR_DOUBLE, ca_element_count ( chan ),
1960  chan, pWF );
1961  SEVCHK ( status, "array write request failed" );
1962 
1963  /*
1964  * read back the array
1965  */
1966  status = ca_array_get ( DBR_DOUBLE, ca_element_count (chan),
1967  chan, pRF );
1968  SEVCHK ( status, "array read request failed" );
1969  status = ca_pend_io ( timeoutToPendIO );
1970  SEVCHK ( status, "array read failed" );
1971 
1972  /*
1973  * verify read response matches values written
1974  */
1975  for ( i = 0; i < ca_element_count ( chan ); i++ ) {
1976  if ( pWF[i] != pRF[i] ) {
1977  printf ( "i=%u, pWF[i]=%f, pRF[i]=%f\n",
1978  i, pWF[i], pRF[i]);
1979  }
1980  verify ( pWF[i] == pRF[i] );
1981  }
1982 
1983  /*
1984  * read back the array as strings
1985  */
1986  {
1987  char *pRS;
1988  unsigned size = ca_element_count (chan) * MAX_STRING_SIZE;
1989 
1990  if ( size <= maxArrayBytes ) {
1991 
1992  pRS = malloc ( ca_element_count (chan) * MAX_STRING_SIZE );
1993  verify ( pRS );
1994  status = ca_array_get ( DBR_STRING,
1995  ca_element_count (chan), chan, pRS );
1996  SEVCHK ( status, "array read request failed" );
1997  status = ca_pend_io ( timeoutToPendIO );
1998  SEVCHK ( status, "array read failed" );
1999  free ( pRS );
2000  }
2001  else {
2002  printf ( "skipping the fetch array in string data type test - does not fit\n" );
2003  }
2004  }
2005 
2006  /*
2007  * write some random numbers into the array
2008  */
2009  for ( i = 0; i < ca_element_count (chan); i++ ) {
2010  pWF[i] = rand ();
2011  pRF[i] = - pWF[i];
2012  }
2013  status = ca_array_put_callback ( DBR_DOUBLE, ca_element_count (chan),
2014  chan, pWF, arrayWriteNotify, 0 );
2015  SEVCHK ( status, "array write notify request failed" );
2016  status = ca_array_get_callback ( DBR_DOUBLE, ca_element_count (chan),
2017  chan, arrayReadNotify, pWF );
2018  SEVCHK ( status, "array read notify request failed" );
2019  ca_flush_io ();
2020  while ( ! arrayWriteNotifyComplete || ! arrayReadNotifyComplete ) {
2021  epicsThreadSleep ( 0.1 );
2022  ca_poll (); /* emulate typical GUI */
2023  }
2024 
2025  /*
2026  * write some random numbers into the array
2027  */
2028  for ( i = 0; i < ca_element_count (chan); i++ ) {
2029  pWF[i] = rand ();
2030  pRF[i] = - pWF[i];
2031  }
2032  arrayReadNotifyComplete = 0;
2033  status = ca_array_put ( DBR_DOUBLE, ca_element_count ( chan ),
2034  chan, pWF );
2035  SEVCHK ( status, "array write notify request failed" );
2036  status = ca_add_array_event ( DBR_DOUBLE, ca_element_count ( chan ),
2037  chan, arrayReadNotify, pWF, 0.0, 0.0, 0.0, &id );
2038  SEVCHK ( status, "array subscription request failed" );
2039  ca_flush_io ();
2040  while ( ! arrayReadNotifyComplete ) {
2041  epicsThreadSleep ( 0.1 );
2042  ca_poll (); /* emulate typical GUI */
2043  }
2044  status = ca_clear_event ( id );
2045  SEVCHK ( status, "clear event request failed" );
2046 
2047  /*
2048  * a get request should fail or fill with zeros
2049  * when the array size is too large
2050  */
2051  {
2052  acctstExceptionCount = 0u;
2054  SEVCHK ( status, "exception notify install failed" );
2055  status = ca_array_get ( DBR_DOUBLE,
2056  ca_element_count (chan)+1, chan, pRF );
2057  if ( status == ECA_NORMAL ) {
2058  ca_poll ();
2059  while ( acctstExceptionCount < 1u ) {
2060  printf ( "N" );
2061  fflush ( stdout );
2062  epicsThreadSleep ( 0.1 );
2063  ca_poll (); /* emulate typical GUI */
2064  }
2065  }
2066  else {
2067  verify ( status == ECA_BADCOUNT );
2068  }
2069  status = ca_add_exception_event ( 0, 0 );
2070  SEVCHK ( status, "exception notify install failed" );
2071  }
2072 
2073  free ( pRF );
2074  free ( pWF );
2075 
2076  showProgressEnd ( interestLevel );
2077 }
2078 
2079 /*
2080  * verify that unequal send/recv buffer sizes work
2081  * (a bug related to this test was detected in early R3.14)
2082  *
2083  * this test must be run when no other channels are connected
2084  */
2085 void unequalServerBufferSizeTest ( const char * pName, unsigned interestLevel )
2086 {
2087  dbr_double_t *pRF, *pWF;
2088  unsigned connections;
2089  chid newChan;
2090  int status;
2091 
2092  showProgressBegin ( "unequalServerBufferSizeTest", interestLevel );
2093 
2094  /* this test must be run when no channels are connected */
2095  connections = ca_get_ioc_connection_count ();
2096  verify ( connections == 0u );
2097 
2098  status = ca_create_channel ( pName, 0, 0, 0, & newChan );
2099  verify ( status == ECA_NORMAL );
2100  status = ca_pend_io ( timeoutToPendIO );
2101  verify ( status == ECA_NORMAL );
2102 
2103  showProgress ( interestLevel );
2104 
2105  if ( ! ca_write_access ( newChan ) ) {
2106  printf ( "skipping unequal buffer size test - no write access\n" );
2107  status = ca_clear_channel ( newChan );
2108  verify ( status == ECA_NORMAL );
2109  return;
2110  }
2111 
2112  pRF = (dbr_double_t *) calloc ( ca_element_count (newChan), sizeof (*pRF) );
2113  verify ( pRF != NULL );
2114 
2115  pWF = (dbr_double_t *) calloc ( ca_element_count (newChan), sizeof (*pWF) );
2116  verify ( pWF != NULL );
2117 
2118  status = ca_array_get ( DBR_DOUBLE, ca_element_count ( newChan ),
2119  newChan, pRF );
2120  status = ca_pend_io ( timeoutToPendIO );
2121  verify ( status == ECA_NORMAL );
2122  status = ca_clear_channel ( newChan );
2123  verify ( status == ECA_NORMAL );
2124 
2125  showProgress ( interestLevel );
2126 
2127  status = ca_create_channel ( pName, 0, 0, 0, &newChan );
2128  verify ( status == ECA_NORMAL );
2129  status = ca_pend_io ( timeoutToPendIO );
2130  verify ( status == ECA_NORMAL );
2131 
2132  showProgress ( interestLevel );
2133 
2134  status = ca_array_put ( DBR_DOUBLE, ca_element_count ( newChan ),
2135  newChan, pWF );
2136  verify ( status == ECA_NORMAL );
2137  status = ca_array_get ( DBR_DOUBLE, 1,
2138  newChan, pRF );
2139  verify ( status == ECA_NORMAL );
2140  status = ca_pend_io ( timeoutToPendIO );
2141  verify ( status == ECA_NORMAL );
2142  status = ca_clear_channel ( newChan );
2143  verify ( status == ECA_NORMAL );
2144 
2145  free ( pRF );
2146  free ( pWF );
2147 
2148  showProgressEnd ( interestLevel );
2149 }
2150 
2151 /*
2152  * pend_event_delay_test()
2153  */
2155 {
2156  int status;
2157  epicsTimeStamp end_time;
2158  epicsTimeStamp start_time;
2159  dbr_double_t delay;
2160  dbr_double_t accuracy;
2161 
2162  epicsTimeGetCurrent ( &start_time );
2163  status = ca_pend_event ( request );
2164  if (status != ECA_TIMEOUT) {
2165  SEVCHK(status, NULL);
2166  }
2167  epicsTimeGetCurrent(&end_time);
2168  delay = epicsTimeDiffInSeconds ( &end_time, &start_time );
2169  accuracy = 100.0*(delay-request)/request;
2170  printf ( "CA pend event delay = %f sec results in error = %f %%\n",
2171  request, accuracy );
2172  verify ( fabs(accuracy) < 10.0 );
2173 }
2174 
2175 void caTaskExitTest ( unsigned interestLevel )
2176 {
2177  int status;
2178 
2179  showProgressBegin ( "caTaskExitTest", interestLevel );
2180 
2181  status = ca_task_exit ();
2182  SEVCHK ( status, NULL );
2183 
2184  showProgressEnd ( interestLevel );
2185 }
2186 
2188 {
2189  int type;
2190 
2191  type = dbf_type_to_DBR ( DBF_SHORT );
2192  verify ( type == DBR_SHORT );
2193  type = dbf_type_to_DBR_STS ( DBF_SHORT );
2194  verify ( type == DBR_STS_SHORT );
2195  type = dbf_type_to_DBR_GR ( DBF_SHORT );
2196  verify ( type == DBR_GR_SHORT );
2197  type = dbf_type_to_DBR_CTRL ( DBF_SHORT );
2198  verify ( type == DBR_CTRL_SHORT );
2199  type = dbf_type_to_DBR_TIME ( DBF_SHORT );
2200  verify ( type == DBR_TIME_SHORT );
2201  verify ( strcmp ( dbr_type_to_text( DBR_SHORT ), "DBR_SHORT" ) == 0 );
2202  verify ( strcmp ( dbf_type_to_text( DBF_SHORT ), "DBF_SHORT" ) == 0 );
2206  {
2207  int dataType = -1;
2208  dbf_text_to_type ( "DBF_SHORT", dataType );
2209  verify ( dataType == DBF_SHORT );
2210  dbr_text_to_type ( "DBR_CLASS_NAME", dataType );
2211  verify ( dataType == DBR_CLASS_NAME );
2212  }
2213 }
2214 
2215 typedef struct {
2218  unsigned count;
2219 } eventTest;
2220 
2221 /*
2222  * updateTestEvent ()
2223  */
2225 {
2226  eventTest *pET = (eventTest *) args.usr;
2227  struct dbr_gr_float *pGF = (struct dbr_gr_float *) args.dbr;
2228  pET->lastValue = pGF->value;
2229  pET->count++;
2230 }
2231 
2233 {
2234  return ( (float) iter ) * 10.12345f + 10.7f;
2235 }
2236 
2238 {
2239  int status;
2240  status = ca_clear_channel ( args.chid );
2241  SEVCHK ( status, "clearChannelInXxxxCallbackTest clear channel" );
2242 }
2243 
2244 void clearChannelInGetCallbackTest ( const char *pName, unsigned level )
2245 {
2246  unsigned i;
2247  chid chan;
2248  int status;
2249 
2250  showProgressBegin ( "clearChannelInGetCallbackTest", level );
2251 
2252  for ( i = 0; ca_get_ioc_connection_count () > 0 ; i++ ) {
2253  ca_pend_event ( 0.1 );
2254  verify ( i < 100 );
2255  }
2256 
2257  status = ca_create_channel ( pName, 0, 0, 0, & chan );
2258  SEVCHK ( status, "clearChannelInGetCallbackTest create channel" );
2259 
2260  status = ca_pend_io ( timeoutToPendIO );
2261  SEVCHK ( status, "clearChannelInGetCallbackTest connect channel" );
2262 
2263  status = ca_get_callback ( DBR_DOUBLE, chan, callbackClearsChannel, 0 );
2264  SEVCHK ( status, "clearChannelInGetCallbackTest get callback" );
2265 
2266  for ( i = 0; ca_get_ioc_connection_count () > 0 ; i++ ) {
2267  ca_pend_event ( 0.1 );
2268  verify ( i < 100 );
2269  }
2270 
2271  showProgressEnd ( level );
2272 }
2273 
2274 void clearChannelInPutCallbackTest ( const char *pName, unsigned level )
2275 {
2276  unsigned i;
2277  const dbr_double_t value = 1.1;
2278  chid chan;
2279  int status;
2280 
2281  showProgressBegin ( "clearChannelInPutCallbackTest", level );
2282 
2283  for ( i = 0; ca_get_ioc_connection_count () > 0 ; i++ ) {
2284  ca_pend_event ( 0.1 );
2285  verify ( i < 100 );
2286  }
2287 
2288  status = ca_create_channel ( pName, 0, 0, 0, & chan );
2289  SEVCHK ( status, "clearChannelInPutCallbackTest create channel" );
2290 
2291  status = ca_pend_io ( timeoutToPendIO );
2292  SEVCHK ( status, "clearChannelInPutCallbackTest connect channel" );
2293 
2294  status = ca_put_callback ( DBR_DOUBLE, chan, & value,
2295  callbackClearsChannel, 0 );
2296  SEVCHK ( status, "clearChannelInPutCallbackTest get callback" );
2297 
2298  for ( i = 0; ca_get_ioc_connection_count () > 0 ; i++ ) {
2299  ca_pend_event ( 0.1 );
2300  verify ( i < 100 );
2301  }
2302 
2303  showProgressEnd ( level );
2304 }
2305 
2306 void clearChannelInSubscrCallbackTest ( const char *pName, unsigned level )
2307 {
2308  unsigned i;
2309  chid chan;
2310  int status;
2311 
2312  showProgressBegin ( "clearChannelInSubscrCallbackTest", level );
2313 
2314  for ( i = 0; ca_get_ioc_connection_count () > 0 ; i++ ) {
2315  ca_pend_event ( 0.1 );
2316  verify ( i < 100 );
2317  }
2318 
2319  status = ca_create_channel ( pName, 0, 0, 0, & chan );
2320  SEVCHK ( status, "clearChannelInSubscrCallbackTest create channel" );
2321 
2322  status = ca_pend_io ( timeoutToPendIO );
2323  SEVCHK ( status, "clearChannelInSubscrCallbackTest connect channel" );
2324 
2325  status = ca_create_subscription ( DBR_DOUBLE, 1, chan,
2327  SEVCHK ( status, "clearChannelInSubscrCallbackTest subscribe" );
2328 
2329  for ( i = 0; ca_get_ioc_connection_count () > 0 ; i++ ) {
2330  ca_pend_event ( 0.1 );
2331  verify ( i < 100 );
2332  }
2333 
2334  showProgressEnd ( level );
2335 }
2336 
2338 {
2339  if ( args.op == CA_OP_CONN_UP ) {
2340  unsigned * pEventCount = ( unsigned * ) ca_puser ( args.chid );
2341  int status;
2342  verify ( *pEventCount == 0u );
2343  (*pEventCount)++;
2344  status = ca_create_subscription ( DBR_DOUBLE, 1,
2345  args.chid, DBE_VALUE, nUpdatesTester, ca_puser ( args.chid ), 0 );
2346  SEVCHK ( status, "monitorAddConnectionCallback create subscription" );
2347  }
2348  else {
2349  fprintf ( stderr, "disconnect during monitorAddConnectionCallbackTest?\n" );
2350  }
2351 }
2352 
2353 /*
2354  * monitorAddConnectionCallbackTest
2355  * 1) subscription add from within connection callback needs to work
2356  * 2) check for problems where subscription is installed twice if
2357  * its installed within the connection callback handler
2358  */
2359 void monitorAddConnectionCallbackTest ( const char *pName, unsigned interestLevel )
2360 {
2361  unsigned i;
2362  chid chan;
2363  int status;
2364  unsigned eventCount = 0u;
2365  unsigned getCallbackCount = 0u;
2366 
2367  showProgressBegin ( "monitorAddConnectionCallbackTest", interestLevel );
2368 
2369  for ( i = 0; ca_get_ioc_connection_count () > 0 ; i++ ) {
2370  ca_pend_event ( 0.1 );
2371  verify ( i < 100 );
2372  }
2373 
2374  status = ca_create_channel ( pName,
2375  monitorAddConnectionCallback, &eventCount, 0, & chan );
2376  SEVCHK ( status, "monitorAddConnectionCallbackTest create channel" );
2377 
2378  while ( eventCount < 2 ) {
2379  ca_pend_event ( 0.1 );
2380  }
2381  verify ( eventCount >= 2u );
2382 
2383  status = ca_get_callback ( DBR_DOUBLE, chan, nUpdatesTester, &getCallbackCount );
2384  SEVCHK ( status, "monitorAddConnectionCallback get callback" );
2385  while ( getCallbackCount == 0 ) {
2386  ca_pend_event ( 0.1 );
2387  }
2388  verify ( eventCount >= 2u );
2389  verify ( getCallbackCount == 1u );
2390 
2391  status = ca_clear_channel ( chan );
2392  SEVCHK ( status, "monitorAddConnectionCallbackTest clear channel" );
2393 
2394  status = ca_flush_io ();
2395  SEVCHK ( status, "monitorAddConnectionCallbackTest flush" );
2396 
2397  showProgressEnd ( interestLevel );
2398 }
2399 
2400 
2401 /*
2402  * monitorUpdateTest
2403  *
2404  * 1) verify we can add many monitors at once
2405  * 2) verify that under heavy load the last monitor
2406  * returned is the last modification sent
2407  */
2408 void monitorUpdateTest ( chid chan, unsigned interestLevel )
2409 {
2410  eventTest test[100];
2411  dbr_float_t temp, getResp;
2412  unsigned i, j;
2413  unsigned flowCtrlCount = 0u;
2414  unsigned prevPassCount;
2415  unsigned tries;
2416 
2417  if ( ! ca_write_access ( chan ) ) {
2418  printf ("skipped monitorUpdateTest test - no write access\n");
2419  return;
2420  }
2421 
2422  if ( dbr_value_class[ca_field_type ( chan )] != dbr_class_float ) {
2423  printf ("skipped monitorUpdateTest test - not an analog type\n");
2424  return;
2425  }
2426 
2427  showProgressBegin ( "monitorUpdateTest", interestLevel );
2428 
2429  /*
2430  * set channel to known value
2431  */
2432  temp = 1;
2433  SEVCHK ( ca_put ( DBR_FLOAT, chan, &temp ), NULL );
2434 
2435  for ( i = 0; i < NELEMENTS(test); i++ ) {
2436  test[i].count = 0;
2437  test[i].lastValue = -1.0f;
2439  &test[i], &test[i].id),NULL);
2440  }
2441 
2442  /*
2443  * force all of the monitors subscription requests to
2444  * complete
2445  *
2446  * NOTE: this hopefully demonstrates that when the
2447  * server is very busy with monitors the client
2448  * is still able to punch through with a request.
2449  */
2450  SEVCHK ( ca_get ( DBR_FLOAT, chan, &getResp) ,NULL );
2451  SEVCHK ( ca_pend_io ( timeoutToPendIO ) ,NULL );
2452 
2453  showProgress ( interestLevel );
2454 
2455  /*
2456  * pass the test only if we get the first monitor update
2457  */
2458  tries = 0;
2459  while ( 1 ) {
2460  unsigned nFailed = 0u;
2461  epicsThreadSleep ( 0.1 );
2462  ca_poll (); /* emulate typical GUI */
2463  for ( i = 0; i < NELEMENTS ( test ); i++ ) {
2464  if ( test[i].count > 0 ) {
2465  if ( test[i].lastValue != temp ) {
2466  nFailed++;
2467  }
2468  }
2469  else {
2470  nFailed++;
2471  }
2472  }
2473  if ( nFailed == 0u ) {
2474  break;
2475  }
2476  printf ( "-" );
2477  fflush ( stdout );
2478  verify ( tries++ < 50 );
2479  }
2480 
2481  showProgress ( interestLevel );
2482 
2483  /*
2484  * attempt to uncover problems where the last event isnt sent
2485  * and hopefully get into a flow control situation
2486  */
2487  prevPassCount = 0u;
2488  for ( i = 0; i < 10; i++ ) {
2489  for ( j = 0; j < NELEMENTS(test); j++ ) {
2490  SEVCHK ( ca_clear_event ( test[j].id ), NULL );
2491  test[j].count = 0;
2492  test[j].lastValue = -1.0f;
2494  &test[j], &test[j].id ) , NULL );
2495  }
2496 
2497  for ( j = 0; j <= i; j++ ) {
2498  temp = monitorUpdateTestPattern ( j );
2499  SEVCHK ( ca_put ( DBR_FLOAT, chan, &temp ), NULL );
2500  }
2501 
2502  /*
2503  * wait for the above to complete
2504  */
2505  getResp = -1;
2506  SEVCHK ( ca_get ( DBR_FLOAT, chan, &getResp ), NULL );
2507  SEVCHK ( ca_pend_io ( timeoutToPendIO ), NULL );
2508 
2509  if ( getResp != temp ) {
2510  printf ( "getResp=%f, temp=%f\n", getResp, temp );
2511  verify ( getResp == temp );
2512  }
2513 
2514  /*
2515  * wait for all of the monitors to have correct values
2516  */
2517  tries = 0;
2518  while (1) {
2519  unsigned passCount = 0;
2520  unsigned tmpFlowCtrlCount = 0u;
2521  epicsThreadSleep ( 0.1 );
2522  ca_poll (); /* emulate typical GUI */
2523  for ( j = 0; j < NELEMENTS ( test ); j++ ) {
2524  /*
2525  * we shouldnt see old monitors because
2526  * we resubscribed
2527  */
2528  verify ( test[j].count <= i + 2 );
2529  if ( test[j].lastValue == temp ) {
2530  if ( test[j].count < i + 1 ) {
2531  tmpFlowCtrlCount++;
2532  }
2533  passCount++;
2534  }
2535  }
2536  if ( passCount == NELEMENTS ( test ) ) {
2537  flowCtrlCount += tmpFlowCtrlCount;
2538  break;
2539  }
2540  if ( passCount == prevPassCount ) {
2541  verify ( tries++ < 500 );
2542  if ( tries % 50 == 0 ) {
2543  for ( j = 0; j <= i; j++ ) {
2545  if ( pat == test[0].lastValue ) {
2546  break;
2547  }
2548  }
2549  if ( j <= i) {
2550  printf ( "-(%d)", i-j );
2551  }
2552  else {
2553  printf ( "." );
2554  }
2555  fflush ( stdout );
2556  }
2557  }
2558  prevPassCount = passCount;
2559  }
2560  }
2561 
2562  showProgress ( interestLevel );
2563 
2564  /*
2565  * delete the event subscriptions
2566  */
2567  for ( i = 0; i < NELEMENTS ( test ); i++ ) {
2568  SEVCHK ( ca_clear_event ( test[i].id ), NULL );
2569  }
2570 
2571  /*
2572  * force all of the clear event requests to
2573  * complete
2574  */
2575  SEVCHK ( ca_get ( DBR_FLOAT, chan, &temp ), NULL );
2576  SEVCHK ( ca_pend_io ( timeoutToPendIO ), NULL );
2577 
2578  /* printf ( "flow control bypassed %u events\n", flowCtrlCount ); */
2579 
2580  showProgressEnd ( interestLevel );
2581 }
2582 
2583 void verifyReasonableBeaconPeriod ( chid chan, unsigned interestLevel )
2584 {
2585  if ( ca_get_ioc_connection_count () > 0 ) {
2586  double beaconPeriod;
2587  double watchDogDelay;
2588  unsigned i;
2589 
2590  showProgressBegin ( "verifyReasonableBeaconPeriod", interestLevel );
2591 
2592 
2593  printf ( "Beacon anomalies detected since program start %u\n",
2595 
2596  beaconPeriod = ca_beacon_period ( chan );
2597  printf ( "Estimated beacon period for channel %s = %g sec.\n",
2598  ca_name ( chan ), beaconPeriod );
2599 
2600  watchDogDelay = ca_receive_watchdog_delay ( chan );
2601  verify ( watchDogDelay >= 0.0 );
2602 
2603  printf ( "busy: receive watchdog for \"%s\" expires in %g sec.\n",
2604  ca_name ( chan ), watchDogDelay );
2605 
2606  /*
2607  * let one default connection timeout go by w/o receive activity
2608  * so we can see if beacons reset the watchdog
2609  */
2610  for ( i = 0u; i < 15u; i++ ) {
2611  ca_pend_event ( 2.0 );
2612  showProgress ( interestLevel );
2613  }
2614  if ( interestLevel > 0 ) {
2615  printf ( "\n" );
2616  }
2617 
2618  watchDogDelay = ca_receive_watchdog_delay ( chan );
2619  verify ( watchDogDelay >= 0.0 );
2620 
2621  printf ( "inactive: receive watchdog for \"%s\" expires in %g sec.\n",
2622  ca_name ( chan ), watchDogDelay );
2623 
2624  showProgressEnd ( interestLevel );
2625  }
2626 }
2627 
2628 void verifyOldPend ( unsigned interestLevel )
2629 {
2630  int status;
2631 
2632  showProgressBegin ( "verifyOldPend", interestLevel );
2633 
2634  /*
2635  * verify that the old ca_pend() is in the symbol table
2636  */
2637  status = ca_pend ( 100000.0, 1 );
2638  verify ( status == ECA_NORMAL );
2639  status = ca_pend ( 1e-12, 0 );
2640  verify ( status == ECA_TIMEOUT );
2641 
2642  showProgressEnd ( interestLevel );
2643 }
2644 
2645 void verifyTimeStamps ( chid chan, unsigned interestLevel )
2646 {
2647  struct dbr_time_double first;
2648  struct dbr_time_double last;
2649  epicsTimeStamp localTime;
2650  char buf[128];
2651  size_t length;
2652  double diff;
2653  int status;
2654 
2655  showProgressBegin ( "verifyTimeStamps", interestLevel );
2656 
2657  status = epicsTimeGetCurrent ( & localTime );
2658  verify ( status >= 0 );
2659 
2660  status = ca_get ( DBR_TIME_DOUBLE, chan, & first );
2661  SEVCHK ( status, "fetch of dbr time double failed\n" );
2662  status = ca_pend_io ( timeoutToPendIO );
2663  verify ( status == ECA_NORMAL );
2664 
2665  status = ca_get ( DBR_TIME_DOUBLE, chan, & last );
2666  SEVCHK ( status, "fetch of dbr time double failed\n" );
2667  status = ca_pend_io ( timeoutToPendIO );
2668  verify ( status == ECA_NORMAL );
2669 
2670  length = epicsTimeToStrftime ( buf, sizeof ( buf ),
2671  "%a %b %d %Y %H:%M:%S.%f", & first.stamp );
2672  verify ( length );
2673  printf ("Processing time of channel \"%s\" was \"%s\"\n",
2674  ca_name ( chan ), buf );
2675 
2676  diff = epicsTimeDiffInSeconds ( & last.stamp, & first.stamp );
2677  printf ("Time difference between two successive reads was %g sec\n",
2678  diff );
2679 
2680  diff = epicsTimeDiffInSeconds ( & first.stamp, & localTime );
2681  printf ("Time difference between client and server %g sec\n",
2682  diff );
2683 
2684  showProgressEnd ( interestLevel );
2685 }
2686 
2687 /*
2688  * attempts to verify from the client side that
2689  * channel priorities work correctly
2690  */
2691 void verifyChannelPriorities ( const char *pName, unsigned interestLevel )
2692 {
2693  static const unsigned nPrio = 30;
2694  unsigned i;
2695 
2696  showProgressBegin ( "verifyChannelPriorities", interestLevel );
2697 
2698  for ( i = 0u; i < nPrio; i++ ) {
2699  int status;
2700  double value;
2701  chid chan0, chan1;
2702  unsigned priority0, priority1;
2703 
2704  priority0 = ( i * ( CA_PRIORITY_MAX - CA_PRIORITY_MIN ) ) / nPrio;
2705  priority0 += CA_PRIORITY_MIN;
2706  if ( priority0 > CA_PRIORITY_MAX ) {
2707  priority0 = CA_PRIORITY_MAX;
2708  }
2709 
2710  priority1 = ( (i+1) * ( CA_PRIORITY_MAX - CA_PRIORITY_MIN ) ) / nPrio;
2711  priority1 += CA_PRIORITY_MIN;
2712  if ( priority1 > CA_PRIORITY_MAX ) {
2713  priority1 = CA_PRIORITY_MAX;
2714  }
2715 
2716  status = ca_create_channel ( pName, 0, 0,
2717  priority0, &chan0 );
2718  SEVCHK ( status, "prioritized channel create failed" );
2719 
2720  status = ca_create_channel ( pName, 0, 0,
2721  priority1, &chan1 );
2722  SEVCHK ( status, "prioritized channel create failed" );
2723 
2724  status = ca_pend_io ( timeoutToPendIO );
2725  SEVCHK ( status, "prioritized channel connect failed" );
2726  verify ( status == ECA_NORMAL );
2727 
2728  value = i;
2729  status = ca_put ( DBR_DOUBLE, chan0, &value );
2730  SEVCHK ( status, "prioritized channel put failed" );
2731  status = ca_put ( DBR_DOUBLE, chan1, &value );
2732  SEVCHK ( status, "prioritized channel put failed" );
2733 
2734  status = ca_flush_io ();
2735  SEVCHK ( status, "prioritized channel flush failed" );
2736 
2737  status = ca_get ( DBR_DOUBLE, chan0, &value );
2738  SEVCHK ( status, "prioritized channel get failed" );
2739  status = ca_get ( DBR_DOUBLE, chan1, &value );
2740  SEVCHK ( status, "prioritized channel get failed" );
2741 
2742  status = ca_pend_io ( timeoutToPendIO );
2743  SEVCHK ( status, "prioritized channel pend io failed" );
2744 
2745  status = ca_clear_channel ( chan0 );
2746  SEVCHK ( status, "prioritized channel clear failed" );
2747  status = ca_clear_channel ( chan1 );
2748  SEVCHK ( status, "prioritized channel clear failed" );
2749  }
2750 
2751  showProgressEnd ( interestLevel );
2752 }
2753 
2754 void verifyTearDownWhenChannelConnected ( const char * pName,
2756  unsigned interestLevel )
2757 {
2758  static const unsigned chanCount = 20;
2759  static const unsigned loopCount = 100;
2760 
2761  chid * const pChans = (chid * const) calloc ( chanCount, sizeof ( *pChans ) );
2762  double * const pValues = (double * const) calloc ( chanCount, sizeof ( *pValues ) );
2763  unsigned i, j;
2764 
2765  verify ( pChans && pValues );
2766 
2767  showProgressBegin ( "verifyTearDownWhenChannelConnected", interestLevel );
2768 
2769  for ( i = 0u; i < loopCount; i++ ) {
2770  int status;
2771  ca_context_create ( select );
2772 
2773  for ( j = 0; j < chanCount; j++ ) {
2774  status = ca_create_channel ( pName, 0, 0, 0, & pChans[j] );
2775  SEVCHK ( status, "immediate tear down channel create failed" );
2776  }
2777  status = ca_pend_io ( timeoutToPendIO );
2778  SEVCHK ( status, "immediate tear down channel connect failed" );
2779  verify ( status == ECA_NORMAL );
2780 
2781  for ( j = 0; j < chanCount; j++ ) {
2782  status = ca_get ( DBR_DOUBLE, pChans[j], &pValues[j] );
2783  SEVCHK ( status, "immediate tear down channel get failed" );
2784  }
2785 
2786  status = ca_pend_io ( timeoutToPendIO );
2787  SEVCHK ( status, "immediate tear down get pend io failed" );
2788 
2789  ca_context_destroy ();
2790  }
2791 
2792  ca_context_create ( select );
2793 
2794  free ( pChans );
2795  free ( pValues );
2796 
2797  showProgressEnd ( interestLevel );
2798 }
2799 
2800 
2801 void verifyImmediateTearDown ( const char * pName,
2803  unsigned interestLevel )
2804 {
2805  int i;
2806 
2807  showProgressBegin ( "verifyImmediateTearDown", interestLevel );
2808 
2809  for ( i = 0u; i < 100; i++ ) {
2810  chid chan;
2811  int status;
2812  dbr_long_t value = i % 8;
2813  ca_context_create ( select );
2814  ca_task_initialize ();
2815  status = ca_create_channel ( pName, 0, 0, 0, & chan );
2816  SEVCHK ( status, "immediate tear down channel create failed" );
2817  status = ca_pend_io ( timeoutToPendIO );
2818  SEVCHK ( status, "immediate tear down channel connect failed" );
2819  verify ( status == ECA_NORMAL );
2820  /*
2821  * verify that puts pending when we call ca_task_exit()
2822  * get flushed out
2823  */
2824  if ( i > 0 ) {
2825  dbr_long_t currentValue = value;
2826  status = ca_get ( DBR_LONG, chan, & currentValue );
2827  SEVCHK ( status, "immediate tear down channel get failed" );
2828  status = ca_pend_io ( timeoutToPendIO );
2829  SEVCHK ( status, "immediate tear down channel get failed" );
2830  if ( currentValue != ( (i - 1) % 8 ) ) {
2831  printf ( "currentValue = %i, i = %i\n", currentValue, i );
2832  verify ( currentValue == ( (i - 1) % 8 ) );
2833  }
2834  }
2835  status = ca_put ( DBR_LONG, chan, & value );
2836  SEVCHK ( status, "immediate tear down channel put failed" );
2837  status = ca_clear_channel ( chan );
2838  SEVCHK ( status, "immediate tear down channel clear failed" );
2839  ca_context_destroy ();
2840  /* epicsThreadSleep ( 1e-15 ); */
2841  if ( i % 10 == 0 ) {
2842  showProgress ( interestLevel );
2843  }
2844  }
2845 
2846  ca_context_create ( select );
2847 
2848  showProgressEnd ( interestLevel );
2849 }
2850 
2851 /*
2852  * keeping these tests together detects a bug
2853  */
2854 void eventClearAndMultipleMonitorTest ( chid chan, unsigned interestLevel )
2855 {
2856  eventClearTest ( chan );
2857  monitorUpdateTest ( chan, interestLevel );
2858 }
2859 
2860 void fdcb ( void * parg )
2861 {
2862  ca_poll ();
2863 }
2864 
2865 void fdRegCB ( void * parg, int fd, int opened )
2866 {
2867  int status;
2868 
2869  fdctx * mgrCtx = ( fdctx * ) parg;
2870  if ( opened ) {
2871  status = fdmgr_add_callback (
2872  mgrCtx, fd, fdi_read, fdcb, 0 );
2873  verify ( status >= 0 );
2874  }
2875  else {
2876  status = fdmgr_clear_callback (
2877  mgrCtx, fd, fdi_read );
2878  verify ( status >= 0 );
2879  }
2880 }
2881 
2882 typedef struct {
2883  char m_chanName[100u];
2895 
2896 static void testMultithreadSubscrSubscrCallback
2897  ( struct event_handler_args eha )
2898 {
2899  const epicsEventId firstUpdateEvent = ( epicsEventId ) eha.usr;
2900  epicsEventSignal ( firstUpdateEvent );
2901 }
2902 
2903 static void testMultithreadSubscrCreateSubscr ( void * pParm )
2904 {
2905  static unsigned nElem = 0;
2906  int testComplete = FALSE;
2907  evid id;
2908  epicsEventId firstUpdateEvent;
2909  epicsEventWaitStatus eventWaitStatus;
2910  MultiThreadSubscrTest * const pMultiThreadSubscrTest =
2911  ( MultiThreadSubscrTest * ) pParm;
2912 
2913  /* this is required for the ca_flush below to work correctly */
2914  int status = ca_attach_context ( pMultiThreadSubscrTest->m_pCtx );
2915  verify ( status == ECA_NORMAL );
2916  firstUpdateEvent = epicsEventMustCreate ( epicsEventEmpty );
2917  verify ( firstUpdateEvent );
2918  status = ca_create_subscription (
2919  DBR_TIME_LONG,
2920  nElem,
2921  pMultiThreadSubscrTest->m_chan,
2922  DBE_VALUE,
2923  testMultithreadSubscrSubscrCallback,
2924  firstUpdateEvent,
2925  & id );
2926  verify ( status == ECA_NORMAL );
2927  status = ca_flush_io ();
2928  verify ( status == ECA_NORMAL );
2929  /* wait for first update */
2930  eventWaitStatus = epicsEventWaitWithTimeout (
2931  firstUpdateEvent, 60.0 * 10 );
2932  verify ( eventWaitStatus == epicsEventWaitOK );
2933  epicsEventDestroy ( firstUpdateEvent );
2934  status = ca_clear_subscription ( id );
2935  verify ( status == ECA_NORMAL );
2936  epicsMutexMustLock ( pMultiThreadSubscrTest->m_mutex );
2937  pMultiThreadSubscrTest->m_nUpdatesReceived++;
2938  testComplete = ( pMultiThreadSubscrTest->m_nUpdatesReceived ==
2939  pMultiThreadSubscrTest->m_nUpdatesRequired );
2940  pMultiThreadSubscrTest->m_testComplete = testComplete;
2941  epicsMutexUnlock ( pMultiThreadSubscrTest->m_mutex );
2942  if ( testComplete ) {
2943  epicsEventSignal ( pMultiThreadSubscrTest->m_testCompleteEvent );
2944  }
2945 }
2946 
2948 {
2949  MultiThreadSubscrTest * const pMultiThreadSubscrTest =
2950  ( MultiThreadSubscrTest * ) ca_puser ( args.chid );
2951  epicsMutexMustLock ( pMultiThreadSubscrTest->m_mutex );
2952  if ( !pMultiThreadSubscrTest->m_testInitiated &&
2953  args.op == CA_OP_CONN_UP ) {
2954  int i;
2955  pMultiThreadSubscrTest->m_testInitiated = TRUE;
2956  for ( i = 0; i < pMultiThreadSubscrTest->m_nUpdatesRequired; i++ ) {
2957  char threadname[64];
2958  epicsThreadId threadId;
2959  sprintf(threadname, "testSubscr%06u", i);
2960  threadId = epicsThreadCreate ( threadname,
2963  testMultithreadSubscrCreateSubscr,
2964  pMultiThreadSubscrTest );
2965  verify ( threadId );
2966  }
2967  }
2968  epicsMutexUnlock ( pMultiThreadSubscrTest->m_mutex );
2969 }
2970 
2971 void testMultithreadSubscr ( void * pParm )
2972 {
2973  MultiThreadSubscrTest * const pMultiThreadSubscrTest =
2974  ( MultiThreadSubscrTest * ) pParm;
2975  int status;
2976  unsigned i;
2977 
2979  verify ( status == ECA_NORMAL );
2980  pMultiThreadSubscrTest->m_pCtx = ca_current_context ();
2981  verify ( pMultiThreadSubscrTest->m_pCtx );
2982  status = ca_create_channel (
2983  pMultiThreadSubscrTest->m_chanName,
2985  pMultiThreadSubscrTest,
2987  & pMultiThreadSubscrTest->m_chan );
2988  verify ( status == ECA_NORMAL );
2989 
2990  showProgressBegin ( "verifyMultithreadSubscr",
2991  pMultiThreadSubscrTest->m_interestLevel );
2992  i = 0;
2993  while ( TRUE ) {
2994  int success = FALSE;
2995  epicsEventWaitStatus eventWaitStatus;
2996  epicsMutexMustLock ( pMultiThreadSubscrTest->m_mutex );
2997  success = pMultiThreadSubscrTest->m_testComplete;
2998  epicsMutexUnlock ( pMultiThreadSubscrTest->m_mutex );
2999  if ( success ) {
3000  break;
3001  }
3002  eventWaitStatus = epicsEventWaitWithTimeout (
3003  pMultiThreadSubscrTest->m_testCompleteEvent, 0.1 );
3004  verify ( eventWaitStatus == epicsEventWaitOK ||
3005  eventWaitStatus == epicsEventWaitTimeout );
3006  if ( i++ % 100 == 0u )
3007  showProgress ( pMultiThreadSubscrTest->m_interestLevel );
3008  verify ( i < 1000 );
3009  }
3010  showProgressEnd ( pMultiThreadSubscrTest->m_interestLevel );
3011 
3012  status = ca_clear_channel ( pMultiThreadSubscrTest->m_chan );
3013  verify ( status == ECA_NORMAL );
3014  ca_context_destroy ();
3015  epicsEventSignal ( pMultiThreadSubscrTest->m_threadExitEvent );
3016 }
3017 
3018 /*
3019  * test installation of subscriptions similar to usage paterns
3020  * employed by modern versions of the sequencer
3021  */
3022 void verifyMultithreadSubscr ( const char * pName, unsigned interestLevel )
3023 {
3024  static unsigned nSubscr = 3000;
3025  epicsThreadId threadId;
3026  MultiThreadSubscrTest * const pMultiThreadSubscrTest =
3027  (MultiThreadSubscrTest*) calloc ( 1,
3028  sizeof ( MultiThreadSubscrTest ) );
3029  verify ( pMultiThreadSubscrTest);
3030  pMultiThreadSubscrTest->m_mutex = epicsMutexMustCreate ();
3031  verify ( pMultiThreadSubscrTest->m_mutex );
3032  pMultiThreadSubscrTest->m_testCompleteEvent =
3034  verify ( pMultiThreadSubscrTest->m_testCompleteEvent );
3035  pMultiThreadSubscrTest->m_threadExitEvent =
3037  verify ( pMultiThreadSubscrTest->m_threadExitEvent );
3038  strncpy ( pMultiThreadSubscrTest->m_chanName, pName,
3039  sizeof ( pMultiThreadSubscrTest->m_chanName ) );
3040  pMultiThreadSubscrTest->m_chanName
3041  [ sizeof ( pMultiThreadSubscrTest->m_chanName ) - 1u ] = '\0';
3042  pMultiThreadSubscrTest->m_nUpdatesRequired = nSubscr;
3043  pMultiThreadSubscrTest->m_interestLevel = interestLevel;
3044  threadId = epicsThreadCreate (
3045  "testMultithreadSubscr",
3048  testMultithreadSubscr, pMultiThreadSubscrTest );
3049  verify ( threadId );
3050  {
3051  epicsEventWaitStatus eventWaitStatus;
3052  eventWaitStatus = epicsEventWaitWithTimeout (
3053  pMultiThreadSubscrTest->m_threadExitEvent, 1000.0 );
3054  verify ( eventWaitStatus == epicsEventWaitOK );
3055  }
3056  epicsEventDestroy ( pMultiThreadSubscrTest->m_testCompleteEvent );
3057  epicsEventDestroy ( pMultiThreadSubscrTest->m_threadExitEvent );
3058  epicsMutexDestroy ( pMultiThreadSubscrTest->m_mutex );
3059  free ( pMultiThreadSubscrTest );
3060 }
3061 
3062 void fdManagerVerify ( const char * pName, unsigned interestLevel )
3063 {
3064  int status;
3065  fdctx * mgrCtx;
3066  struct timeval tmo;
3067  chid newChan;
3069  unsigned eventCount = 0u;
3070  epicsTimeStamp begin, end;
3071 
3072  mgrCtx = fdmgr_init ();
3073  verify ( mgrCtx );
3074 
3075  showProgressBegin ( "fdManagerVerify", interestLevel );
3076 
3077  status = ca_add_fd_registration ( fdRegCB, mgrCtx );
3078  verify ( status == ECA_NORMAL );
3079 
3080  status = ca_create_channel ( pName, 0, 0, 0, & newChan );
3081  verify ( status == ECA_NORMAL );
3082 
3083  while ( ca_state ( newChan ) != cs_conn ) {
3084  tmo.tv_sec = 6000;
3085  tmo.tv_usec = 0;
3086  status = fdmgr_pend_event ( mgrCtx, & tmo );
3087  verify ( status >= 0 );
3088  }
3089 
3090  showProgress ( interestLevel );
3091 
3092  status = ca_add_event ( DBR_FLOAT, newChan,
3093  nUpdatesTester, & eventCount, & subscription );
3094  verify ( status == ECA_NORMAL );
3095 
3096  status = ca_flush_io ();
3097  verify ( status == ECA_NORMAL );
3098 
3099  while ( eventCount < 1 ) {
3100  tmo.tv_sec = 6000;
3101  tmo.tv_usec = 0;
3102  status = fdmgr_pend_event ( mgrCtx, & tmo );
3103  verify ( status >= 0 );
3104  }
3105 
3106  showProgress ( interestLevel );
3107 
3108  status = ca_clear_event ( subscription );
3109  verify ( status == ECA_NORMAL );
3110 
3111  status = ca_flush_io ();
3112  verify ( status == ECA_NORMAL );
3113 
3114  /* look for infinite loop in fd manager schedualing */
3115  epicsTimeGetCurrent ( & begin );
3116  eventCount = 0u;
3117  while ( 1 ) {
3118  double delay;
3119  tmo.tv_sec = 1;
3120  tmo.tv_usec = 0;
3121  status = fdmgr_pend_event ( mgrCtx, & tmo );
3122  verify ( status >= 0 );
3123  epicsTimeGetCurrent ( & end );
3124  delay = epicsTimeDiffInSeconds ( & end, & begin );
3125  if ( delay >= 1.0 ) {
3126  break;
3127  }
3128  verify ( eventCount++ < 100 );
3129  }
3130 
3131  showProgress ( interestLevel );
3132 
3133  status = ca_clear_channel ( newChan );
3134  verify ( status == ECA_NORMAL );
3135 
3136  status = ca_add_fd_registration ( 0, 0 );
3137  verify ( status == ECA_NORMAL );
3138 
3139  status = fdmgr_delete ( mgrCtx );
3140  verify ( status >= 0 );
3141 
3142  showProgressEnd ( interestLevel );
3143 }
3144 
3146  const char *pName, unsigned interestLevel )
3147 {
3148  int status;
3149  chid bogusChan[300];
3150  chid validChan;
3151  unsigned i;
3152 
3153  showProgressBegin ( "verifyConnectWithDisconnectedChannels", interestLevel );
3154 
3155  for ( i= 0u; i < NELEMENTS ( bogusChan ); i++ ) {
3156  char buf[256];
3157  sprintf ( buf, "aChannelThatShouldNeverNeverNeverExist%u", i );
3158  status = ca_create_channel ( buf, 0, 0, 0, & bogusChan[i] );
3159  verify ( status == ECA_NORMAL );
3160  }
3161 
3162  status = ca_pend_io ( 0.001 );
3163  verify ( status == ECA_TIMEOUT );
3164 
3165  /* wait a long time for the search interval to increase */
3166  for ( i= 0u; i < 10; i++ ) {
3167  epicsThreadSleep ( 1.0 );
3168  showProgress ( interestLevel );
3169  }
3170 
3171  status = ca_create_channel ( pName, 0, 0, 0, & validChan );
3172  verify ( status == ECA_NORMAL );
3173 
3174  /*
3175  * we should be able to connect to a valid
3176  * channel within a reasonable delay even
3177  * though there is one permanently
3178  * diasconnected channel
3179  */
3180  status = ca_pend_io ( timeoutToPendIO );
3181  verify ( status == ECA_NORMAL );
3182 
3183  status = ca_clear_channel ( validChan );
3184  verify ( status == ECA_NORMAL );
3185 
3186  for ( i= 0u; i < NELEMENTS ( bogusChan ); i++ ) {
3187  status = ca_clear_channel ( bogusChan[i] );
3188  verify ( status == ECA_NORMAL );
3189  }
3190 
3191  showProgressEnd ( interestLevel );
3192 }
3193 
3195  struct connection_handler_args args )
3196 {
3197  int * pDisconnectFlag = ca_puser ( args.chid );
3198  if ( args.op == CA_OP_CONN_DOWN ) {
3199  ca_clear_channel ( args.chid );
3200  *pDisconnectFlag = 1;
3201  }
3202 }
3203 
3205 {
3206 }
3207 
3209  const char * pName, unsigned interestLevel )
3210 {
3211  int disconnectFlag = 0;
3212  unsigned count = 0;
3213  chid chan0;
3214  chid chan1;
3215  int status;
3216 
3217  status = ca_create_channel (
3219  & disconnectFlag, 0, & chan0 );
3220  SEVCHK ( status, NULL );
3221 
3222  fprintf ( stdout, "Waiting for test channel to connect." );
3223  fflush ( stdout );
3224  do {
3225  ca_pend_event ( 0.1 );
3226  if ( count++%50 == 0 ) {
3227  fprintf ( stdout, "." );
3228  fflush ( stdout );
3229  }
3230  } while ( ca_state ( chan0 ) != cs_conn );
3231  fprintf ( stdout, "confirmed.\n" );
3232 
3233  /*
3234  * if its a local channel and will never disconnect
3235  * then skip the portions of this test that cant be
3236  * completed.
3237  */
3238  if ( ca_get_ioc_connection_count () == 0 ) {
3239  status = ca_clear_channel ( chan0 );
3240  SEVCHK ( status, NULL );
3241  return;
3242  }
3243 
3245  SEVCHK ( status, NULL );
3246 
3247  fprintf ( stdout, "Please force test channel to disconnect." );
3248  fflush ( stdout );
3249  do {
3250  ca_pend_event ( 0.1 );;
3251  if ( count++%50 == 0 ) {
3252  fprintf ( stdout, "." );
3253  fflush ( stdout );
3254  }
3255  } while ( ! disconnectFlag );
3256  fprintf ( stdout, "confirmed.\n" );
3257  /* channel cleared by disconnect handler */
3258 
3259  status = ca_create_channel (
3260  pName, 0, 0, 0, & chan1 );
3261  SEVCHK ( status, NULL );
3262 
3263  fprintf ( stdout, "Waiting for test channel to connect." );
3264  fflush ( stdout );
3265  while ( ca_state ( chan1 ) != cs_conn ) {
3266  ca_pend_event ( 5.0 );
3267  fprintf ( stdout, "." );
3268  fflush ( stdout );
3269  }
3270  status = ca_clear_channel ( chan1 );
3271  SEVCHK ( status, NULL );
3272  fprintf ( stdout, "confirmed.\n" );
3273 
3274  status = ca_add_exception_event ( 0, 0 );
3275  SEVCHK ( status, NULL );
3276 }
3277 
3279  const char * pName, unsigned interestLevel )
3280 {
3281  chid chan;
3282  int status = ca_create_channel (
3283  pName, 0, 0, 0, & chan );
3284  SEVCHK ( status, NULL );
3285  if ( strcmp ( pName, ca_name ( chan ) ) != 0 ) {
3286  printf ( "Canonical name for channel was \"%s\"\n", ca_name ( chan ) );
3287  }
3288  status = ca_clear_channel ( chan );
3289  SEVCHK ( status, NULL );
3290 }
3291 
3292 void verifyContextRundownFlush ( const char * pName, unsigned interestLevel )
3293 {
3294  unsigned i;
3295 
3296  showProgressBegin ( "verifyContextRundownFlush", interestLevel );
3297 
3298  for ( i=0u; i < 1000; i++ ) {
3299  const dbr_double_t stim = i;
3300 
3301  {
3302  chid chan;
3303  int status;
3305  SEVCHK ( status, "context create failed" );
3306 
3307  status = ca_create_channel ( pName, 0, 0, 0, & chan );
3308  /*
3309  * currently in-memory channels cant be used with this test
3310  * !!!! FIX ME, FIX ME, FIX ME, FIX ME !!!!
3311  */
3312  if ( status != ECA_UNAVAILINSERV ) {
3313  SEVCHK ( status, NULL );
3314 
3315  status = ca_pend_io( timeoutToPendIO );
3316  SEVCHK ( status, "channel connect failed" );
3317 
3318  status = ca_put ( DBR_DOUBLE, chan, & stim );
3319  SEVCHK ( status, "channel put failed" );
3320 
3321  status = ca_clear_channel ( chan );
3322  SEVCHK ( status, NULL );
3323  }
3324  ca_context_destroy ();
3325  }
3326 
3327  {
3328  chid chan;
3329  int status;
3330  dbr_double_t resp;
3332  SEVCHK ( status, "context create failed" );
3333 
3334  status = ca_create_channel ( pName, 0, 0, 0, & chan );
3335  SEVCHK ( status, NULL );
3336  /*
3337  * currently in-memory channels cant be used with this test
3338  * !!!! FIX ME, FIX ME, FIX ME, FIX ME !!!!
3339  */
3340  if ( status != ECA_UNAVAILINSERV ) {
3341  status = ca_pend_io( timeoutToPendIO );
3342  SEVCHK ( status, "channel connect failed" );
3343 
3344  status = ca_get ( DBR_DOUBLE, chan, & resp );
3345  SEVCHK ( status, "channel get failed" );
3346 
3347  status = ca_pend_io ( timeoutToPendIO );
3348  SEVCHK ( status, "get, pend io failed" );
3349 
3350  verify ( stim == resp );
3351 
3352  status = ca_clear_channel ( chan );
3353  SEVCHK ( status, NULL );
3354  }
3355  ca_context_destroy ();
3356  }
3357 
3358  if ( i % 100 == 0 ) {
3359  showProgress ( interestLevel );
3360  }
3361  }
3362 
3363  showProgressEnd ( interestLevel );
3364 }
3365 
3367  const char * pName, unsigned interestLevel )
3368 {
3369  chid chan[10000];
3370  int status;
3371  unsigned i;
3372 
3373  showProgressBegin ( "verifyContextRundownChanStillExist", interestLevel );
3374 
3376  SEVCHK ( status, "context create failed" );
3377 
3378  for ( i = 0; i < NELEMENTS ( chan ); i++ ) {
3379  status = ca_create_channel ( pName, 0, 0, 0, & chan[i] );
3380  /*
3381  * currently in-memory channels cant be used with this test
3382  * !!!! FIX ME, FIX ME, FIX ME, FIX ME !!!!
3383  */
3384  if ( status == ECA_UNAVAILINSERV ) {
3385  break;
3386  }
3387  SEVCHK ( status, NULL );
3388  }
3389 
3390  status = ca_pend_io( timeoutToPendIO );
3391  SEVCHK ( status, "channel connect failed" );
3392 
3393  ca_context_destroy ();
3394 
3395  showProgressEnd ( interestLevel );
3396 }
3397 
3398 int acctst ( const char * pName, unsigned interestLevel, unsigned channelCount,
3399  unsigned repetitionCount, enum ca_preemptive_callback_select select )
3400 {
3401  chid chan;
3402  int status;
3403  unsigned i;
3404  appChan *pChans;
3405  unsigned connections;
3406  unsigned maxArrayBytes = 10000000;
3407 
3408  printf ( "CA Client V%s, channel name \"%s\", timeout %g\n",
3409  ca_version (), pName, timeoutToPendIO );
3410  if ( select == ca_enable_preemptive_callback ) {
3411  printf ( "Preemptive call back is enabled.\n" );
3412  }
3413 
3414  {
3415  char tmpString[32];
3416  sprintf ( tmpString, "%u", maxArrayBytes );
3417  epicsEnvSet ( "EPICS_CA_MAX_ARRAY_BYTES", tmpString );
3418  }
3419 
3420  /*
3421  * this test creates, and then destroys, a private CA context
3422  */
3423  multiSubscrDestroyNoLateCallbackTest ( pName, interestLevel );
3424 
3425  status = ca_context_create ( select );
3426  SEVCHK ( status, NULL );
3427 
3428  verifyDisconnect ( pName, interestLevel );
3429  verifyImmediateTearDown ( pName, select, interestLevel );
3430  verifyTearDownWhenChannelConnected ( pName, select, interestLevel );
3431 
3433 
3434  connections = ca_get_ioc_connection_count ();
3435  verify ( connections == 0u );
3436  unequalServerBufferSizeTest ( pName, interestLevel );
3437  clearChannelInGetCallbackTest ( pName, interestLevel );
3438  clearChannelInPutCallbackTest ( pName, interestLevel );
3439  clearChannelInSubscrCallbackTest ( pName, interestLevel );
3440  monitorAddConnectionCallbackTest ( pName, interestLevel );
3441 
3442  showProgressBegin ( "connecting to test channel", interestLevel );
3443  status = ca_search ( pName, & chan );
3444  SEVCHK ( status, NULL );
3445  status = ca_pend_io ( timeoutToPendIO );
3446  SEVCHK ( status, NULL );
3447  showProgressEnd ( interestLevel );
3448 
3449  printf ( "native type was %s, native count was %lu\n",
3450  dbf_type_to_text ( ca_field_type ( chan ) ),
3451  ca_element_count ( chan ) );
3452 
3453  connections = ca_get_ioc_connection_count ();
3454  verify ( connections == 1u || connections == 0u );
3455  if ( connections == 0u ) {
3456  printf ( "testing with a local channel\n" );
3457  }
3458 
3459  verifyName ( pName, interestLevel );
3460  verifyConnectWithDisconnectedChannels ( pName, interestLevel );
3461  grEnumTest ( chan, interestLevel );
3462  test_sync_groups ( chan, interestLevel );
3463  verifyChannelPriorities ( pName, interestLevel );
3464  verifyTimeStamps ( chan, interestLevel );
3465  verifyOldPend ( interestLevel );
3466  exceptionTest ( chan, interestLevel );
3467  arrayTest ( chan, maxArrayBytes, interestLevel );
3468  verifyMonitorSubscriptionFlushIO ( chan, interestLevel );
3469  monitorSubscriptionFirstUpdateTest ( pName, chan, interestLevel );
3470  ctrlDoubleTest ( chan, interestLevel );
3471  verifyBlockInPendIO ( chan, interestLevel );
3472  verifyAnalogIO ( chan, DBR_FLOAT, FLT_MIN, FLT_MAX,
3473  FLT_MIN_EXP, FLT_MAX_EXP, FLT_EPSILON, interestLevel );
3474  verifyAnalogIO ( chan, DBR_DOUBLE, DBL_MIN, DBL_MAX,
3475  DBL_MIN_EXP, DBL_MAX_EXP, DBL_EPSILON, interestLevel );
3476  verifyLongIO ( chan, interestLevel );
3477  verifyShortIO ( chan, interestLevel );
3478  multiSubscriptionDeleteTest ( chan, interestLevel );
3479  singleSubscriptionDeleteTest ( chan, interestLevel );
3480  channelClearWithEventTrafficTest ( pName, interestLevel );
3481  eventClearAndMultipleMonitorTest ( chan, interestLevel );
3482  verifyHighThroughputRead ( chan, interestLevel );
3483  verifyHighThroughputWrite ( chan, interestLevel );
3484  verifyHighThroughputReadCallback ( chan, interestLevel );
3485  verifyHighThroughputWriteCallback ( chan, interestLevel );
3486  verifyBadString ( chan, interestLevel );
3487  verifyMultithreadSubscr ( pName, interestLevel );
3488  if ( select != ca_enable_preemptive_callback ) {
3489  fdManagerVerify ( pName, interestLevel );
3490  }
3491 
3492  /*
3493  * CA pend event delay accuracy test
3494  * (CA asssumes that search requests can be sent
3495  * at least every 25 mS on all supported os)
3496  */
3497  printf ( "\n" );
3498  pend_event_delay_test ( 1.0 );
3499  pend_event_delay_test ( 0.1 );
3500  pend_event_delay_test ( 0.25 );
3501 
3502  /* ca_channel_status ( 0 ); */
3503  ca_client_status ( 0 );
3504  /* ca_client_status ( 6u ); info about each channel */
3505 
3506  pChans = calloc ( channelCount, sizeof ( *pChans ) );
3507  verify ( pChans );
3508 
3509  for ( i = 0; i < channelCount; i++ ) {
3510  strncpy ( pChans[ i ].name, pName, sizeof ( pChans[ i ].name ) );
3511  pChans[ i ].name[ sizeof ( pChans[i].name ) - 1 ] = '\0';
3512  }
3513 
3514  verifyConnectionHandlerConnect ( pChans, channelCount, repetitionCount, interestLevel );
3515  verifyBlockingConnect ( pChans, channelCount, repetitionCount, interestLevel );
3516  verifyClear ( pChans, interestLevel );
3517 
3518  verifyReasonableBeaconPeriod ( chan, interestLevel );
3519 
3520  /*
3521  * Verify that we can do IO with the new types for ALH
3522  */
3523 #if 0
3524  if ( ca_read_access (chan) && ca_write_access (chan) ) {
3525  {
3526  dbr_put_ackt_t acktIn = 1u;
3527  dbr_put_acks_t acksIn = 1u;
3528  struct dbr_stsack_string stsackOut;
3529 
3530  SEVCHK ( ca_put ( DBR_PUT_ACKT, chan, &acktIn ), NULL );
3531  SEVCHK ( ca_put ( DBR_PUT_ACKS, chan, &acksIn ), NULL );
3532  SEVCHK ( ca_get ( DBR_STSACK_STRING, chan, &stsackOut ), NULL );
3533  SEVCHK ( ca_pend_io ( timeoutToPendIO ), NULL );
3534  }
3535 #endif
3536 
3537  /* test that ca_task_exit () works when there is still one channel remaining */
3538  /* status = ca_clear_channel ( chan ); */
3539  /* SEVCHK ( status, NULL ); */
3540 
3541  caTaskExitTest ( interestLevel );
3542 
3543  verifyContextRundownFlush ( pName, interestLevel );
3544  verifyContextRundownChanStillExist ( pName, interestLevel );
3545 
3546  free ( pChans );
3547 
3548  printf ( "\nTest Complete\n" );
3549 
3550  epicsExit ( EXIT_SUCCESS );
3551 
3552  return 0;
3553 }
3554 
3555 
void verifyDataTypeMacros(void)
Definition: acctst.c:2187
LIBCA_API int epicsStdCall ca_replace_access_rights_event(chid chan, caArh *pfunc)
void ctrlDoubleTest(chid chan, unsigned interestLevel)
Definition: acctst.c:751
void arrayReadNotify(struct event_handler_args args)
Definition: acctst.c:1911
void noopSubscriptionStateChange(struct event_handler_args args)
Definition: acctst.c:373
void verifyClear(appChan *pChans, unsigned interestLevel)
Definition: acctst.c:684
LIBCOM_API void epicsEventMustTrigger(epicsEventId id)
Trigger an event.
Definition: epicsEvent.cpp:116
void monitorAddConnectionCallback(struct connection_handler_args args)
Definition: acctst.c:2337
int epicsStdCall ca_task_exit()
Definition: access.cpp:251
#define DBR_STRING
Definition: db_access.h:69
void noopExceptionCallback(struct exception_handler_args args)
Definition: acctst.c:3204
#define CA_OP_CONN_UP
Definition: cadef.h:128
void verifyClearChannelOnDisconnectCallback(struct connection_handler_args args)
Definition: acctst.c:3194
epicsThreadId epicsStdCall epicsThreadMustCreate(const char *name, unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC funptr, void *parm)
void nUpdatesTester(struct event_handler_args args)
Definition: acctst.c:106
dbr_double_t value
Definition: db_access.h:299
Definition: link.h:174
#define max(x, y)
Definition: flexdef.h:81
LIBCOM_API int epicsStdCall fdmgr_pend_event(fdctx *pfdctx, struct timeval *ptimeout)
Definition: fdmgr.cpp:298
LIBCA_API int epicsStdCall ca_array_get_callback(chtype type, unsigned long count, chid chanId, caEventCallBackFunc *pFunc, void *pArg)
dbr_long_t upper_ctrl_limit
Definition: db_access.h:495
LIBCA_API unsigned epicsStdCall ca_write_access(chid chan)
struct epicsEventOSD * epicsEventId
An identifier for an epicsEvent for use with the C API.
Definition: epicsEvent.h:46
std::string request
#define dbf_type_to_DBR_STS(type)
Definition: db_access.h:701
#define FALSE
Definition: dbDefs.h:32
const void * dbr
Definition: cadef.h:89
LIBCA_API int epicsStdCall ca_v42_ok(chid chan)
void verifyName(const char *pName, unsigned interestLevel)
Definition: acctst.c:3278
#define dbf_type_to_text(type)
Definition: db_access.h:677
#define multiSubscrDestroyNoLateCallbackEventCount
Definition: acctst.c:1332
epicsMutexId m_mutex
Definition: acctst.c:2886
unsigned epicsStdCall ca_beacon_anomaly_count()
Definition: access.cpp:681
#define CA_PRIORITY_DEFAULT
Definition: cadef.h:192
evid id
Definition: acctst.c:2216
void epicsStdCall epicsMutexDestroy(epicsMutexId pmutexNode)
Destroy an epicsMutex semaphore.
Definition: epicsMutex.cpp:127
void monitorAddConnectionCallbackTest(const char *pName, unsigned interestLevel)
Definition: acctst.c:2359
pvd::Status status
#define epicsThreadPriorityMedium
Definition: epicsThread.h:76
An EPICS-specific replacement for ANSI C&#39;s assert.
void monitorUpdateTest(chid chan, unsigned interestLevel)
Definition: acctst.c:2408
#define verify(exp)
Definition: acctst.c:65
void ioTesterEvent(struct event_handler_args args)
Definition: acctst.c:258
void fdctx
Definition: fdmgr.h:36
void singleSubscriptionDeleteTest(chid chan, unsigned interestLevel)
Definition: acctst.c:1570
int i
Definition: scan.c:967
void monitorSubscriptionFirstUpdateTest(const char *pName, chid chan, unsigned interestLevel)
Definition: acctst.c:118
void verifyContextRundownFlush(const char *pName, unsigned interestLevel)
Definition: acctst.c:3292
#define ca_poll()
Definition: cadef.h:564
#define ECA_IOINPROGRESS
Definition: caerr.h:120
void verifyBlockingConnect(appChan *pChans, unsigned chanCount, unsigned repetitionCount, unsigned interestLevel)
Definition: acctst.c:515
size_t m_nUpdatesRequired
Definition: acctst.c:2890
void clearChannelInPutCallbackTest(const char *pName, unsigned level)
Definition: acctst.c:2274
void caTaskExitTest(unsigned interestLevel)
Definition: acctst.c:2175
ca_preemptive_callback_select
Definition: cadef.h:175
unsigned acctstExceptionCount
Definition: acctst.c:1730
LIBCA_API int epicsStdCall ca_array_put_callback(chtype type, unsigned long count, chid chanId, const void *pValue, caEventCallBackFunc *pFunc, void *pArg)
int epicsStdCall ca_create_channel(const char *name_str, caCh *conn_func, void *puser, capri priority, chid *chanptr)
Definition: access.cpp:288
#define min(x, y)
Definition: flexdef.h:78
void clearChannelInGetCallbackTest(const char *pName, unsigned level)
Definition: acctst.c:2244
#define ECA_GETFAIL
Definition: caerr.h:96
void verifyContextRundownChanStillExist(const char *pName, unsigned interestLevel)
Definition: acctst.c:3366
#define DBR_GR_ENUM
Definition: db_access.h:97
void verifyShortIO(chid chan, unsigned interestLevel)
Definition: acctst.c:1068
LIBCA_API unsigned long epicsStdCall ca_element_count(chid chan)
LIBCA_API enum channel_state epicsStdCall ca_state(chid chan)
#define CA_PRIORITY_MAX
Definition: cadef.h:190
int epicsStdCall ca_search_and_connect(const char *name_str, chid *chanptr, caCh *conn_func, void *puser)
Definition: access.cpp:279
evid subscription
Definition: acctst.c:47
dbr_long_t lower_ctrl_limit
Definition: db_access.h:496
void epicsStdCall ca_self_test()
Definition: access.cpp:777
epicsFloat32 dbr_float_t
Definition: db_access.h:46
struct ca_client_context * m_pCtx
Definition: acctst.c:2884
#define ECA_PUTFAIL
Definition: caerr.h:97
void arrayTest(chid chan, unsigned maxArrayBytes, unsigned interestLevel)
Definition: acctst.c:1932
void showProgressBegin(const char *pTestName, unsigned interestLevel)
Definition: acctst.c:68
Routines to get and set EPICS environment parameters.
void floatTest(chid chan, dbr_float_t beginValue, dbr_float_t increment, dbr_float_t epsilon, unsigned iterations)
Definition: acctst.c:872
epicsTimeStamp stamp
Definition: db_access.h:297
void verifyHighThroughputWriteCallback(chid chan, unsigned interestLevel)
Definition: acctst.c:1187
unsigned read_access
Definition: cadef.h:60
void showProgressEnd(unsigned interestLevel)
Definition: acctst.c:81
#define DBR_FLOAT
Definition: db_access.h:72
void acctstExceptionNotify(struct exception_handler_args args)
Definition: acctst.c:1731
int epicsStdCall ca_pend_io(ca_real timeout)
Definition: access.cpp:484
unsigned epicsStdCall ca_get_ioc_connection_count()
Definition: access.cpp:670
#define printf
Definition: epicsStdio.h:41
unsigned CA_SYNC_GID
Definition: cadef.h:113
void fdcb(void *parg)
Definition: acctst.c:2860
pvd::StructureConstPtr type
#define ECA_BADCOUNT
Definition: caerr.h:99
#define ECA_IODONE
Definition: caerr.h:119
size_t m_nUpdatesReceived
Definition: acctst.c:2889
#define INVALID_DB_REQ(x)
Definition: db_access.h:115
LIBCA_API void *epicsStdCall ca_puser(chid chan)
#define epicsMutexMustCreate()
Create an epicsMutex semaphore for use from C code.
Definition: epicsMutex.h:179
#define NULL
Definition: catime.c:38
#define dbf_type_to_DBR(type)
Definition: db_access.h:697
void callbackClearsChannel(struct event_handler_args args)
Definition: acctst.c:2237
void grEnumTest(chid chan, unsigned interestLevel)
Definition: acctst.c:719
unsigned connectionUpdateCount
Definition: acctst.c:52
LIBCA_API int epicsStdCall ca_sg_array_put(const CA_SYNC_GID gid, chtype type, unsigned long count, chid chan, const void *pValue)
Definition: syncgrp.cpp:246
void verifyTimeStamps(chid chan, unsigned interestLevel)
Definition: acctst.c:2645
LIBCOM_API epicsEventStatus epicsEventWaitWithTimeout(epicsEventId id, double timeOut)
Wait an the event or until the specified timeout period is over.
Definition: osdEvent.c:117
evid globalEventID
Definition: acctst.c:1676
#define DBR_PUT_ACKS
Definition: db_access.h:110
void channelClearWithEventTrafficTest(const char *pName, unsigned interestLevel)
Definition: acctst.c:1623
#define DBR_STS_STRING
Definition: db_access.h:77
Definition: cadef.h:166
#define dbr_type_is_SHORT(type)
Definition: db_access.h:658
Definition: fdmgr.h:33
int epicsStdCall ca_attach_context(struct ca_client_context *pCtx)
Definition: access.cpp:746
LIBCOM_API epicsEventId epicsEventMustCreate(epicsEventInitialState initialState)
Create an epicsEvent for use from C code.
Definition: epicsEvent.cpp:106
void test_sync_groups(chid chan, unsigned interestLevel)
Definition: acctst.c:1280
epicsTime begin
Definition: caConnTest.cpp:22
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
Definition: epicsMutex.cpp:140
void multiSubscriptionDeleteTest(chid chan, unsigned interestLevel)
Definition: acctst.c:1494
void getCallbackStateChange(struct event_handler_args args)
Definition: acctst.c:313
Miscellaneous macro definitions.
LIBCA_API int epicsStdCall ca_sg_delete(const CA_SYNC_GID gid)
Definition: syncgrp.cpp:68
LIBCA_API short epicsStdCall ca_field_type(chid chan)
LIBCA_API int epicsStdCall ca_change_connection_event(chid chan, caCh *pfunc)
#define dbr_type_is_valid(type)
Definition: db_access.h:644
#define ca_put(type, chan, pValue)
Definition: cadef.h:302
LIBCOM_API unsigned int epicsStdCall epicsThreadGetStackSize(epicsThreadStackSizeClass size)
Definition: osdThread.c:466
LIBCOM_API void epicsEventMustWait(epicsEventId id)
Wait for an event (see epicsEventWait()).
Definition: epicsEvent.cpp:123
LIBCOM_API int epicsStdCall fdmgr_delete(fdctx *pfdctx)
Definition: fdmgr.cpp:313
LIBCA_API int epicsStdCall ca_sg_create(CA_SYNC_GID *pgid)
Definition: syncgrp.cpp:24
void arrayEventExceptionNotify(struct event_handler_args args)
Definition: acctst.c:1737
int epicsStdCall ca_client_status(unsigned level)
Definition: access.cpp:701
void verifyTearDownWhenChannelConnected(const char *pName, enum ca_preemptive_callback_select select, unsigned interestLevel)
Definition: acctst.c:2754
LIBCOM_API void epicsStdCall epicsEnvSet(const char *name, const char *value)
Set an environment variable&#39;s value.
Definition: osdEnv.c:35
epicsThreadId epicsStdCall epicsThreadCreate(const char *name, unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC funptr, void *parm)
Definition: epicsThread.cpp:33
dbr_short_t lower_ctrl_limit
Definition: db_access.h:435
void fdManagerVerify(const char *pName, unsigned interestLevel)
Definition: acctst.c:3062
#define DBR_STS_SHORT
Definition: db_access.h:78
#define dbf_type_to_DBR_GR(type)
Definition: db_access.h:709
unsigned subscriptionUpdateCount
Definition: acctst.c:50
#define dbr_type_to_text(type)
Definition: db_access.h:687
#define DBR_STSACK_STRING
Definition: db_access.h:111
#define ca_put_callback(type, chan, pValue, pFunc, pArg)
Definition: cadef.h:347
unsigned char connected
Definition: acctst.c:48
dbr_float_t monitorUpdateTestPattern(unsigned iter)
Definition: acctst.c:2232
void multiple_sg_requests(chid chix, CA_SYNC_GID gid)
Definition: acctst.c:1255
#define DBE_VALUE
Definition: caeventmask.h:38
void verifyBadString(chid chan, unsigned interestLevel)
Definition: acctst.c:1219
int epicsStdCall ca_context_create(ca_preemptive_callback_select premptiveCallbackSelect)
Definition: access.cpp:172
int epicsStdCall ca_pend_event(ca_real timeout)
Definition: access.cpp:457
dbr_double_t upper_ctrl_limit
Definition: db_access.h:513
void unequalServerBufferSizeTest(const char *pName, unsigned interestLevel)
Definition: acctst.c:2085
LIBCOM_API size_t epicsStdCall epicsTimeToStrftime(char *pBuff, size_t bufLength, const char *pFormat, const epicsTimeStamp *pTS)
Convert epicsTimeStamp to string. See epicsTime::strftime()
Definition: epicsTime.cpp:1120
unsigned write_access
Definition: cadef.h:61
#define dbf_text_to_type(text, type)
Definition: db_access.h:681
struct MultiSubscrDestroyNoLateCallbackTestData * m_pTestData
Definition: acctst.c:1338
#define dbr_text_to_type(text, type)
Definition: db_access.h:691
dbr_short_t upper_ctrl_limit
Definition: db_access.h:434
#define ca_add_array_event(TYPE, COUNT, CHID, ENTRY, ARG, P_DELTA, N_DELTA, TO, EVID)
Definition: cadef.h:872
void verifyAnalogIO(chid chan, int dataType, double min, double max, int minExp, int maxExp, double epsilon, unsigned interestLevel)
Definition: acctst.c:932
void pend_event_delay_test(dbr_double_t request)
Definition: acctst.c:2154
#define ECA_NORMAL
Definition: caerr.h:77
chid channel
Definition: acctst.c:46
void verifyImmediateTearDown(const char *pName, enum ca_preemptive_callback_select select, unsigned interestLevel)
Definition: acctst.c:2801
#define epicsEventSignal(ID)
A synonym for epicsEventTrigger().
Definition: epicsEvent.h:172
void showProgress(unsigned interestLevel)
Definition: acctst.c:98
#define DBR_CTRL_SHORT
Definition: db_access.h:102
void eventClearAndMultipleMonitorTest(chid chan, unsigned interestLevel)
Definition: acctst.c:2854
LIBCA_API int epicsStdCall ca_array_put(chtype type, unsigned long count, chid chanId, const void *pValue)
APIs for the epicsMutex mutual exclusion semaphore.
int epicsStdCall ca_add_exception_event(caExceptionHandler *pfunc, void *arg)
Definition: access.cpp:402
int epicsStdCall ca_flush_io()
Definition: access.cpp:509
#define SEVCHK(CA_ERROR_CODE, MESSAGE_STRING)
Definition: cadef.h:137
int epicsStdCall epicsTimeGetCurrent(epicsTimeStamp *pDest)
Get current time into *pDest.
#define DBR_DOUBLE
Definition: db_access.h:76
#define VALID_DB_REQ(x)
Definition: db_access.h:114
int epicsStdCall ca_pend(ca_real timeout, int early)
Definition: access.cpp:443
#define ca_get(type, chan, pValue)
Definition: cadef.h:384
#define DBR_GR_DOUBLE
Definition: db_access.h:100
#define CA_PRIORITY_MIN
Definition: cadef.h:191
void verifyConnectionHandlerConnect(appChan *pChans, unsigned chanCount, unsigned repetitionCount, unsigned interestLevel)
Definition: acctst.c:399
#define DBR_TIME_LONG
Definition: db_access.h:91
#define epicsThreadPriorityLow
Definition: epicsThread.h:75
#define DBR_SHORT
Definition: db_access.h:71
void fdRegCB(void *parg, int fd, int opened)
Definition: acctst.c:2865
LIBCOM_API void epicsExit(int status)
Calls epicsExitCallAtExits(), then the OS exit() routine.
Definition: epicsExit.c:182
LIBCA_API int epicsStdCall ca_clear_subscription(evid pMon)
LIBCA_API int epicsStdCall ca_array_get(chtype type, unsigned long count, chid chanId, void *pValue)
BSD and SRV5 Unix timestamp.
Definition: epicsTime.h:52
Extended replacement for the Posix exit and atexit routines.
epicsFloat64 dbr_double_t
Definition: db_access.h:47
LIBCA_API const char *epicsStdCall ca_name(chid chan)
void verifyConnectWithDisconnectedChannels(const char *pName, unsigned interestLevel)
Definition: acctst.c:3145
dbr_double_t lower_ctrl_limit
Definition: db_access.h:514
LIBCOM_API void epicsEventDestroy(epicsEventId id)
Destroy an epicsEvent and any resources it holds.
Definition: osdEvent.c:70
LIBCOM_API int epicsStdCall fdmgr_clear_callback(fdctx *pfdctx, SOCKET fd, enum fdi_type fdi)
Definition: fdmgr.cpp:271
int epicsStdCall ca_task_initialize(void)
Definition: access.cpp:166
int epicsStdCall ca_add_fd_registration(CAFDHANDLER *func, void *arg)
Definition: access.cpp:623
LIBCA_API unsigned epicsStdCall ca_read_access(chid chan)
void testMultithreadSubscrConnHandler(struct connection_handler_args args)
Definition: acctst.c:2947
void connectionStateChange(struct connection_handler_args args)
Definition: acctst.c:329
Definition: acctst.c:44
#define DBR_GR_SHORT
Definition: db_access.h:94
epicsOldString dbr_string_t
Definition: db_access.h:38
int epicsStdCall ca_clear_event(evid pMon)
Definition: access.cpp:431
#define NELEMENTS(A)
Definition: aToIPAddr.c:21
#define stdout
Definition: epicsStdio.h:30
dbr_short_t no_str
Definition: db_access.h:353
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
char name[64]
Definition: acctst.c:45
void verifyReasonableBeaconPeriod(chid chan, unsigned interestLevel)
Definition: acctst.c:2583
int epicsStdCall ca_clear_channel(chid pChan)
Definition: access.cpp:363
unsigned accessUpdateCount
Definition: acctst.c:51
#define ca_search(pChanName, pChanID)
Definition: cadef.h:859
LIBCA_API int epicsStdCall ca_sg_test(const CA_SYNC_GID gid)
Definition: syncgrp.cpp:202
struct MultiSubscrDestroyNoLateCallbackEventData m_eventData[multiSubscrDestroyNoLateCallbackEventCount]
Definition: acctst.c:1347
void verifyDisconnect(const char *pName, unsigned interestLevel)
Definition: acctst.c:3208
APIs for the epicsEvent binary semaphore.
#define DBR_TIME_SHORT
Definition: db_access.h:87
void verifyBlockInPendIO(chid chan, unsigned interestLevel)
Definition: acctst.c:823
#define CA_OP_CONN_DOWN
Definition: cadef.h:129
LIBCA_API int epicsStdCall ca_sg_array_get(const CA_SYNC_GID gid, chtype type, unsigned long count, chid chan, void *pValue)
Definition: syncgrp.cpp:308
epicsMutexLockStatus
Definition: epicsMutex.h:51
LIBCOM_API unsigned int epicsStdCall epicsThreadGetPrioritySelf(void)
Definition: osdThread.c:707
LIBCA_API double epicsStdCall ca_beacon_period(chid chan)
void doubleTest(chid chan, dbr_double_t beginValue, dbr_double_t increment, dbr_double_t epsilon, unsigned iterations)
Definition: acctst.c:901
void verifyHighThroughputWrite(chid chan, unsigned interestLevel)
Definition: acctst.c:1134
epicsMutexLockStatus epicsStdCall epicsMutexLock(epicsMutexId pmutexNode)
Claim the semaphore, waiting until it&#39;s free if currently owned owned by a different thread...
Definition: epicsMutex.cpp:145
const char *epicsStdCall ca_message(long ca_status)
Definition: access.cpp:561
void clearChannelInSubscrCallbackTest(const char *pName, unsigned level)
Definition: acctst.c:2306
const char *epicsStdCall ca_version()
Definition: access.cpp:641
chanId chid
Definition: cadef.h:86
epicsEventId m_testCompleteEvent
Definition: acctst.c:2887
void arrayWriteNotify(struct event_handler_args args)
Definition: acctst.c:1921
#define DBR_CTRL_LONG
Definition: db_access.h:107
#define DBR_GR_FLOAT
Definition: db_access.h:96
LIBCA_API double epicsStdCall ca_receive_watchdog_delay(chid chan)
#define DBR_CLASS_NAME
Definition: db_access.h:112
dbr_value_class
Definition: db_access.h:529
#define epicsThreadPriorityHigh
Definition: epicsThread.h:77
LIBCOM_API int epicsStdCall fdmgr_add_callback(fdctx *pfdctx, SOCKET fd, enum fdi_type fdi, pCallBackFDMgr pFunc, void *pParam)
Definition: fdmgr.cpp:229
#define DBR_LONG
Definition: db_access.h:75
#define MAX_STRING_SIZE
Definition: epicsTypes.h:65
EPICS time stamp, for use from C code.
Definition: epicsTime.h:33
LIBCOM_API fdctx *epicsStdCall fdmgr_init(void)
Definition: fdmgr.cpp:156
void testMultithreadSubscr(void *pParm)
Definition: acctst.c:2971
void verifyLongIO(chid chan, unsigned interestLevel)
Definition: acctst.c:1025
unsigned count
Definition: acctst.c:2218
#define dbr_size_n(TYPE, COUNT)
Definition: db_access.h:518
#define TRUE
Definition: dbDefs.h:27
void verifyHighThroughputReadCallback(chid chan, unsigned interestLevel)
Definition: acctst.c:1158
void selfDeleteEvent(struct event_handler_args args)
Definition: acctst.c:1678
void subscriptionStateChange(struct event_handler_args args)
Definition: acctst.c:359
void exceptionTest(chid chan, unsigned interestLevel)
Definition: acctst.c:1750
LIBCOM_API void epicsStdCall epicsThreadSleep(double seconds)
Block the calling thread for at least the specified time.
Definition: osdThread.c:790
#define epicsEventWaitOK
Old name provided for backwards compatibility.
Definition: epicsEvent.h:58
#define ECA_TIMEOUT
Definition: caerr.h:87
void accessRightsStateChange(struct access_rights_handler_args args)
Definition: acctst.c:302
int * base
Definition: flex.c:92
#define DBR_PUT_ACKT
Definition: db_access.h:109
epicsEventId m_threadExitEvent
Definition: acctst.c:2888
struct appChan appChan
dbr_float_t lastValue
Definition: acctst.c:2217
LIBCOM_API double epicsStdCall epicsTimeDiffInSeconds(const epicsTimeStamp *pLeft, const epicsTimeStamp *pRight)
Time difference between left and right in seconds.
Definition: epicsTime.cpp:1048
void verifyHighThroughputRead(chid chan, unsigned interestLevel)
Definition: acctst.c:1109
#define DBR_TIME_DOUBLE
Definition: db_access.h:92
#define dbf_type_is_valid(type)
Definition: db_access.h:643
unsigned m_interestLevel
Definition: acctst.c:2893
#define ECA_BADTYPE
Definition: caerr.h:91
#define stderr
Definition: epicsStdio.h:32
int acctst(const char *pName, unsigned interestLevel, unsigned channelCount, unsigned repetitionCount, enum ca_preemptive_callback_select select)
Definition: acctst.c:3398
LIBCA_API int epicsStdCall ca_sg_reset(const CA_SYNC_GID gid)
Definition: syncgrp.cpp:155
epicsUInt16 dbr_put_acks_t
Definition: db_access.h:49
EPICS time-stamps (epicsTimeStamp), epicsTime C++ class and C functions for handling wall-clock times...
dbr_double_t value
Definition: db_access.h:515
epicsInt16 dbr_short_t
Definition: db_access.h:40
void verifyOldPend(unsigned interestLevel)
Definition: acctst.c:2628
epicsInt32 dbr_long_t
Definition: db_access.h:44
void epicsStdCall ca_context_destroy()
Definition: access.cpp:232
#define epicsEventWaitStatus
Old name provided for backwards compatibility.
Definition: epicsEvent.h:56
void updateTestEvent(struct event_handler_args args)
Definition: acctst.c:2224
void verifyMonitorSubscriptionFlushIO(chid chan, unsigned interestLevel)
Definition: acctst.c:271
void verifyMultithreadSubscr(const char *pName, unsigned interestLevel)
Definition: acctst.c:3022
#define epicsMutexMustLock(ID)
Claim a semaphore (see epicsMutexLock()).
Definition: epicsMutex.h:214
void ioTesterGet(struct event_handler_args args)
Definition: acctst.c:246
struct ca_client_context *epicsStdCall ca_current_context()
Definition: access.cpp:726
epicsUInt16 dbr_put_ackt_t
Definition: db_access.h:48
void eventClearTest(chid chan)
Definition: acctst.c:1685
void verifyChannelPriorities(const char *pName, unsigned interestLevel)
Definition: acctst.c:2691
#define DBR_CTRL_DOUBLE
Definition: db_access.h:108
dbr_string_t value
Definition: db_access.h:179
#define ca_add_event(type, chan, pFunc, pArg, pEventID)
Definition: cadef.h:866
LIBCA_API int epicsStdCall ca_sg_block(const CA_SYNC_GID gid, ca_real timeout)
Definition: syncgrp.cpp:127
void * usr
Definition: cadef.h:85
unsigned getCallbackCount
Definition: acctst.c:53
#define ca_get_callback(type, chan, pFunc, pArg)
Definition: cadef.h:441
LIBCA_API int epicsStdCall ca_create_subscription(chtype type, unsigned long count, chid chanId, long mask, caEventCallBackFunc *pFunc, void *pArg, evid *pEventID)
#define ECA_UNAVAILINSERV
Definition: caerr.h:131
unsigned char accessRightsHandlerInstalled
Definition: acctst.c:49
LIBCOM_API void epicsStdCall epicsThreadSetPriority(epicsThreadId id, unsigned int priority)
Definition: osdThread.c:713
#define dbf_type_to_DBR_CTRL(type)
Definition: db_access.h:713
char m_chanName[100u]
Definition: acctst.c:2883
int epicsStdCall ca_test_io()
Definition: access.cpp:526
char strs[MAX_ENUM_STATES][MAX_ENUM_STRING_SIZE]
Definition: db_access.h:354
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf(void)
Definition: osdThread.c:810
#define dbf_type_to_DBR_TIME(type)
Definition: db_access.h:705