Mercurial > hg > freeDiameter
view tests/testfifo.c @ 1481:c9e9f8a71946
Update to 3GPP TS 32.299 V15.7.0 (2019-06)
Add AVPs:
- 3GPP-OC-Rating-Group, Unsigned32, code 1321
- 3GPP-OC-Request-Type, Enumerated, code 1322
- 3GPP-OC-Specific-Reduction, Grouped, code 1320
- 3GPP-PS-Data-Off-Status-32.299, Enumerated, code 4406
- API-Content, UTF8String, code 1309
- API-Direction, Enumerated, code 1310
- API-Identifier, OctetString, code 1311
- API-Invocation-Timestamp, Time, code 1312
- API-Network-Service-Node, Enumerated, code 1315
- API-Result-Code, Unsigned32, code 1313
- API-Size, Unsigned64, code 1314
- APN-Rate-Control, Grouped, code 3933
- APN-Rate-Control-Downlink, Grouped, code 3934
- APN-Rate-Control-Uplink, Grouped, code 3935
- Access-Network-Info-Change, Grouped, code 4401
- Additional-Exception-Reports, Enumerated, code 3936
- Announcement-Identifier, Unsigned32, code 3905
- Announcement-Information, Grouped, code 3904
- Announcement-Order, Unsigned32, code 3906
- Announcing-PLMN-ID, UTF8String, code 4408
- Announcing-UE-HPLMN-Identifier, UTF8String, code 3426
- Announcing-UE-VPLMN-Identifier, UTF8String, code 3427
- Application-Specific-Data, OctetString, code 3458
- Authorised-QoS, UTF8String, code 849
- BSSID, UTF8String, code 2716
- Basic-Service-Code, Grouped, code 3411
- Bearer-Capability, OctetString, code 3412
- CN-Operator-Selection-Entity, Enumerated, code 3421
- CP-CIoT-EPS-Optimisation-Indicator, Enumerated, code 3930
- CPDT-Information, Grouped, code 3927
- Called-Identity, UTF8String, code 3916
- Called-Identity-Change, Grouped, code 3917
- Cellular-Network-Information, OctetString, code 3924
- Charging-Per-IP-CAN-Session-Indicator, Enumerated, code 4400
- Civic-Address-Information, UTF8String, code 1305
- Coverage-Info, Grouped, code 3459
- Coverage-Status, Enumerated, code 3428
- Discoveree-UE-HPLMN-Identifier, UTF8String, code 4402
- Discoveree-UE-VPLMN-Identifier, UTF8String, code 4403
- Discoverer-UE-HPLMN-Identifier, UTF8String, code 4404
- Discoverer-UE-VPLMN-Identifier, UTF8String, code 4405
- EPDG-Address, Address, code 3425
- Enhanced-Diagnostics, Grouped, code 3901
- Exposure-Function-API-Information, Grouped, code 1316
- FE-Identifier-List, UTF8String, code 4413
- Forwarding-Pending, Enumerated, code 3415
- IMS-Visited-Network-Identifier, UTF8String, code 2713
- ISUP-Cause, Grouped, code 3416
- ISUP-Cause-Diagnostics, OctetString, code 3422
- ISUP-Cause-Location, Unsigned32, code 3423
- ISUP-Cause-Value, Unsigned32, code 3424
- ISUP-Location-Number, OctetString, code 3414
- Instance-Id, UTF8String, code 3402
- Inter-UE-Transfer, Enumerated, code 3902
- Language, UTF8String, code 3914
- Layer-2-Group-ID, OctetString, code 3429
- Location-Info, Grouped, code 3460
- MBMS-Charged-Party, Enumerated, code 2323
- MSC-Address, OctetString, code 3417
- MTC-IWF-Address, Address, code 3406
- Monitored-PLMN-Identifier, UTF8String, code 3430
- Monitoring-Event-Configuration-Activity, Integer32, code 3919
- Monitoring-Event-Functionality, Integer32, code 3922
- Monitoring-Event-Information, Grouped, code 3921
- Monitoring-Event-Report-Data, Grouped, code 3920
- Monitoring-Event-Report-Number, Unsigned32, code 3923
- Monitoring-UE-HPLMN-Identifier, UTF8String, code 3431
- Monitoring-UE-Identifier, UTF8String, code 3432
- Monitoring-UE-VPLMN-Identifier, UTF8String, code 3433
- NIDD-Submission, Grouped, code 3928
- Network-Call-Reference-Number, OctetString, code 3418
- PC3-Control-Protocol-Cause, Integer32, code 3434
- PC3-EPC-Control-Protocol-Cause, Integer32, code 3435
- PC5-Radio-Technology, Enumerated, code 1300
- Play-Alternative, Enumerated, code 3913
- Privacy-Indicator, Enumerated, code 3915
- ProSe-3rd-Party-Application-ID, UTF8String, code 3440
- ProSe-Direct-Communication-Reception-Data-Container, Grouped, code 3461
- ProSe-Direct-Communication-Transmission-Data-Container, Grouped, code 3441
- ProSe-Direct-Discovery-Model, Enumerated, code 3442
- ProSe-Event-Type, Enumerated, code 3443
- ProSe-Function-IP-Address, Address, code 3444
- ProSe-Function-PLMN-Identifier, UTF8String, code 3457
- ProSe-Functionality, Enumerated, code 3445
- ProSe-Group-IP-Multicast-Address, Address, code 3446
- ProSe-Information, Grouped, code 3447
- ProSe-Range-Class, Enumerated, code 3448
- ProSe-Reason-For-Cancellation, Enumerated, code 3449
- ProSe-Request-Timestamp, Time, code 3450
- ProSe-Role-Of-UE, Enumerated, code 3451
- ProSe-Source-IP-Address, Address, code 3452
- ProSe-Target-Layer-2-ID, OctetString, code 4410
- ProSe-UE-ID, OctetString, code 3453
- ProSe-UE-to-Network-Relay-UE-ID, OctetString, code 4409
- Proximity-Alert-Indication, Enumerated, code 3454
- Proximity-Alert-Timestamp, Time, code 3455
- Proximity-Cancellation-Timestamp, Time, code 3456
- Quota-Indicator, Enumerated, code 3912
- RAN-End-Time, Time, code 1301
- RAN-Secondary-RAT-Usage-Report, Grouped, code 1302
- RAN-Start-Time, Time, code 1303
- Radio-Frequency, OctetString, code 3462
- Radio-Parameter-Set-Info, Grouped, code 3463
- Radio-Parameter-Set-Values, OctetString, code 3464
- Radio-Resources-Indicator, Integer32, code 3465
- Rate-Control-Max-Message-Size, Unsigned32, code 3937
- Rate-Control-Max-Rate, Unsigned32, code 3938
- Rate-Control-Time-Unit, Unsigned32, code 3939
- Reason-Header, UTF8String, code 3401
- Related-Change-Condition-Information, Grouped, code 3925
- Related-IMS-Charging-Identifier, UTF8String, code 2711
- Related-IMS-Charging-Identifier-Node, Address, code 2712
- Related-Trigger, Grouped, code 3926
- Relay-IP-address, Address, code 4411
- Requested-PLMN-Identifier, UTF8String, code 3436
- Requestor-PLMN-Identifier, UTF8String, code 3437
- Role-Of-ProSe-Function, Enumerated, code 3438
- Route-Header-Received, UTF8String, code 3403
- Route-Header-Transmitted, UTF8String, code 3404
- SCEF-Address, Address, code 1317
- SCS-AS-Address, Grouped, code 3940
- SCS-Address, Address, code 3941
- SCS-Realm, DiameterIdentity, code 3942
- SGi-PtP-Tunnelling-Method, Enumerated, code 3931
- SM-Device-Trigger-Indicator, Enumerated, code 3407
- SM-Device-Trigger-Information, Grouped, code 3405
- SM-Sequence-Number, Unsigned32, code 3408
- SMS-Result, Unsigned32, code 3409
- Secondary-RAT-Type, OctetString, code 1304
- Serving-Node-Identity, DiameterIdentity, code 3929
- Start-of-Charging, Time, code 3419
- TAD-Identifier, Enumerated, code 2717
- TLTRI, Unsigned32, code 1318
- TWAG-Address, Address, code 3903
- TWAN-User-Location-Info, Grouped, code 2714
- Target-IP-Address, Address, code 4412
- Teleservice, OctetString, code 3413
- Time-First-Reception, Time, code 3466
- Time-First-Transmission, Time, code 3467
- Time-Indicator, Unsigned32, code 3911
- Transmitter-Info, Grouped, code 3468
- UNI-PDU-CP-Only-Flag, Enumerated, code 3932
- UWAN-User-Location-Info, Grouped, code 3918
- Unused-Quota-Timer, Unsigned32, code 4407
- Usage-Information-Report-Sequence-Number, Integer32, code 3439
- VCS-Information, Grouped, code 3410
- VLR-Number, OctetString, code 3420
- Variable-Part, Grouped, code 3907
- Variable-Part-Order, Unsigned32, code 3908
- Variable-Part-Type, Unsigned32, code 3909
- Variable-Part-Value, UTF8String, code 3910
- WLAN-Operator-Id, Grouped, code 1306
- WLAN-Operator-Name, UTF8String, code 1307
- WLAN-PLMN-Id, UTF8String, code 1308
3GPP TS 32.299 V11.8.0 (2013-07) renamed
LCS-Requestor-Id (1239) to LCS-Requestor-ID (1239).
3GPP TS 32.299 V11.8.0 (2013-07) renamed
LCS-Requestor-Id-String (1240) to LCS-Requestor-ID-String (1240).
3GPP TS 32.299 V13.1.0 (2015-06) renamed
PoC-User-Role-info-Units (1254) to PoC-User-Role-Info-Units (1254).
3GPP TS 32.299 V11.10.0 (2013-12) renamed
Status (2702) to Status-Code (2702), and then
3GPP TS 32.299 V11.14.0 (2014-12) renamed
Status-Code (2702) to Status-AS-Code (2702).
author | Luke Mewburn <luke@mewburn.net> |
---|---|
date | Thu, 26 Mar 2020 15:26:18 +1100 |
parents | 1af09cc156d6 |
children |
line wrap: on
line source
/********************************************************************************************************* * Software License Agreement (BSD License) * * Author: Sebastien Decugis <sdecugis@freediameter.net> * * * * Copyright (c) 2013, WIDE Project and NICT * * All rights reserved. * * * * Redistribution and use of this software in source and binary forms, with or without modification, are * * permitted provided that the following conditions are met: * * * * * Redistributions of source code must retain the above * * copyright notice, this list of conditions and the * * following disclaimer. * * * * * Redistributions in binary form must reproduce the above * * copyright notice, this list of conditions and the * * following disclaimer in the documentation and/or other * * materials provided with the distribution. * * * * * Neither the name of the WIDE Project or NICT nor the * * names of its contributors may be used to endorse or * * promote products derived from this software without * * specific prior written permission of WIDE Project and * * NICT. * * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *********************************************************************************************************/ #include "tests.h" #include <unistd.h> #include <limits.h> /* Wrapper for pthread_barrier stuff on Mac OS X */ #ifndef HAVE_PTHREAD_BAR #define PTHREAD_BARRIER_SERIAL_THREAD 1 typedef struct { int count; int entered; int serial; pthread_mutex_t mutex; pthread_cond_t cond; } pthread_barrier_t; int pthread_barrier_init(pthread_barrier_t * barrier, int * barrier_attr, int count) { memset(barrier, 0, sizeof(pthread_barrier_t)); barrier->count = count; pthread_mutex_init(&barrier->mutex, NULL); pthread_cond_init(&barrier->cond, NULL); return 0; } int pthread_barrier_destroy(pthread_barrier_t * barrier) { pthread_mutex_destroy(&barrier->mutex); pthread_cond_destroy(&barrier->cond); return 0; } int pthread_barrier_wait(pthread_barrier_t * barrier) { int ret = 0; int serial; pthread_mutex_lock(&barrier->mutex); serial = barrier->serial; /* first thread gets the special value */ if (barrier->entered++ == 0) ret = PTHREAD_BARRIER_SERIAL_THREAD; /* Count was achieved? */ if (barrier->entered == barrier->count) { /* Ok, increase serial, reset number of threads, and signal everyone */ barrier->entered = 0; barrier->serial++; pthread_cond_broadcast(&barrier->cond); } else { do { pthread_cond_wait(&barrier->cond, &barrier->mutex); } while (barrier->serial == serial); /* this protects against spurious wakes */ } pthread_mutex_unlock(&barrier->mutex); return 0; } #endif /* HAVE_PTHREAD_BAR */ /* Structure for testing threshold function */ static struct thrh_test { struct fifo * queue; /* pointer to the queue */ int h_calls; /* number of calls of h_cb */ int l_calls; /* number of calls of l_cb */ } thrh_td; /* Callbacks for threasholds test */ void thrh_cb_h(struct fifo *queue, void **data) { if (thrh_td.h_calls == thrh_td.l_calls) { CHECK( NULL, *data ); *data = &thrh_td; } else { CHECK( *data, &thrh_td ); } CHECK( queue, thrh_td.queue ); /* Update the count */ thrh_td.h_calls ++; } void thrh_cb_l(struct fifo *queue, void **data) { CHECK( 1, data ? 1 : 0 ); CHECK( *data, &thrh_td ); /* Check the queue parameter is correct */ CHECK( queue, thrh_td.queue ); /* Update the count */ thrh_td.l_calls ++; /* Cleanup the data ptr if needed */ if (thrh_td.l_calls == thrh_td.h_calls) *data = NULL; /* done */ } /* Structure that is passed to the test function */ struct test_data { struct fifo * queue; /* pointer to the queue */ pthread_barrier_t * bar; /* if not NULL, barrier to synchronize before getting messages */ struct timespec * ts; /* if not NULL, use a timedget instead of a get */ int nbr; /* number of messages to retrieve from the queue */ }; /* The test function, to be threaded */ static void * test_fct(void * data) { int ret = 0, i; struct msg * msg = NULL; struct test_data * td = (struct test_data *) data; if (td->bar != NULL) { ret = pthread_barrier_wait(td->bar); if (ret != PTHREAD_BARRIER_SERIAL_THREAD) { CHECK( 0, ret); } else { CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret); /* just for the traces */ } } for (i=0; i< td->nbr; i++) { if (td->ts != NULL) { CHECK( 0, fd_fifo_timedget(td->queue, &msg, td->ts) ); } else { CHECK( 0, fd_fifo_get(td->queue, &msg) ); } } return NULL; } /* The test function, to be threaded */ static int iter = 0; static void * test_fct2(void * data) { int i; int * item; struct test_data * td = (struct test_data *) data; for (i=0; i< td->nbr; i++) { item = malloc(sizeof(int)); CHECK( 1, item ? 1 : 0 ); *item = i; CHECK( 0, fd_fifo_post(td->queue, &item) ); iter++; } return NULL; } /* Main test routine */ int main(int argc, char *argv[]) { struct timespec ts; struct msg * msg1 = NULL; struct msg * msg2 = NULL; struct msg * msg3 = NULL; /* First, initialize the daemon modules */ INIT_FD(); /* Prolog: create the messages */ { struct dict_object * acr_model = NULL; struct dict_object * cer_model = NULL; struct dict_object * dwr_model = NULL; CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &acr_model, ENOENT ) ); CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &cer_model, ENOENT ) ); CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request", &dwr_model, ENOENT ) ); CHECK( 0, fd_msg_new ( acr_model, 0, &msg1 ) ); CHECK( 0, fd_msg_new ( cer_model, 0, &msg2 ) ); CHECK( 0, fd_msg_new ( dwr_model, 0, &msg3 ) ); } /* Basic operation */ { struct fifo * queue = NULL; struct msg * msg = NULL; int max; long long count; /* Create the queue */ CHECK( 0, fd_fifo_new(&queue, 0) ); /* Check the count is 0 */ CHECK( 0, fd_fifo_length(queue) ); /* Now enqueue */ msg = msg1; CHECK( 0, fd_fifo_post(queue, &msg) ); msg = msg2; CHECK( 0, fd_fifo_post(queue, &msg) ); msg = msg3; CHECK( 0, fd_fifo_post(queue, &msg) ); /* Check the count is 3 */ CHECK( 3, fd_fifo_length(queue) ); /* Retrieve the first message using fd_fifo_get */ CHECK( 0, fd_fifo_get(queue, &msg) ); CHECK( msg1, msg); CHECK( 2, fd_fifo_length(queue) ); /* Retrieve the second message using fd_fifo_timedget */ CHECK(0, clock_gettime(CLOCK_REALTIME, &ts)); ts.tv_sec += 1; /* Set the timeout to 1 second */ CHECK( 0, fd_fifo_timedget(queue, &msg, &ts) ); CHECK( msg2, msg); CHECK( 1, fd_fifo_length(queue) ); /* Retrieve the third message using meq_tryget */ CHECK( 0, fd_fifo_tryget(queue, &msg) ); CHECK( msg3, msg); CHECK( 0, fd_fifo_length(queue) ); /* Check that another meq_tryget does not block */ CHECK( EWOULDBLOCK, fd_fifo_tryget(queue, &msg) ); CHECK( 0, fd_fifo_length(queue) ); /* Check the timedget actually timesout */ CHECK(0, clock_gettime(CLOCK_REALTIME, &ts)); ts.tv_nsec += 1000000; /* 1 millisecond */ if (ts.tv_nsec >= 1000000000L) { ts.tv_nsec -= 1000000000L; ts.tv_sec += 1; } CHECK( ETIMEDOUT, fd_fifo_timedget(queue, &msg, &ts) ); CHECK( 0, fd_fifo_length(queue) ); /* Post & get another message */ msg = msg1; CHECK( 0, fd_fifo_post(queue, &msg) ); CHECK( 0, fd_fifo_timedget(queue, &msg, &ts) ); CHECK( msg1, msg); /* Check some statistics */ CHECK( 0, fd_fifo_getstats(queue, NULL, NULL, &max, &count, NULL, NULL, NULL) ); CHECK( 3, max ); CHECK( 4, count ); /* We're done for basic tests */ CHECK( 0, fd_fifo_del(&queue) ); } /* Test robustness, ensure no messages are lost */ { #define NBR_MSG 200 #define NBR_THREADS 60 struct fifo *queue = NULL; pthread_barrier_t bar; struct test_data td_1; struct test_data td_2; struct msg *msgs[NBR_MSG * NBR_THREADS * 2], *msg; pthread_t thr [NBR_THREADS * 2]; struct dict_object *dwr_model = NULL; int i; int nbr_threads; #ifdef _POSIX_THREAD_THREADS_MAX nbr_threads = _POSIX_THREAD_THREADS_MAX; #else /* _POSIX_THREAD_THREADS_MAX */ nbr_threads = sysconf(_SC_THREAD_THREADS_MAX); #endif /* _POSIX_THREAD_THREADS_MAX */ if ((nbr_threads <= 0) || (nbr_threads > NBR_THREADS * 2)) { nbr_threads = NBR_THREADS; } else { TRACE_DEBUG(INFO, "Local limit on number of threads: %d", nbr_threads); /* The local limit is below NBR_THREADS */ nbr_threads = (nbr_threads / 2) - 1; /* Ensure we create at least a few threads! */ CHECK( 1, nbr_threads >= 10 ? 1 : 0 ); } /* Create the queue */ CHECK( 0, fd_fifo_new(&queue, 0) ); /* Create the barrier */ CHECK( 0, pthread_barrier_init(&bar, NULL, nbr_threads * 2 + 1) ); /* Initialize the ts */ CHECK(0, clock_gettime(CLOCK_REALTIME, &ts)); ts.tv_sec += 20; /* Set the timeout to 20 second */ /* Create the messages */ CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request", &dwr_model, ENOENT ) ); for (i = 0; i < NBR_MSG * nbr_threads * 2; i++) { CHECK( 0, fd_msg_new ( dwr_model, 0, &msgs[i] ) ); } /* Initialize the test data structures */ td_1.queue = queue; td_1.bar = &bar; td_1.ts = &ts; td_1.nbr = NBR_MSG; td_2.queue = queue; td_2.bar = &bar; td_2.ts = NULL; td_2.nbr = NBR_MSG; /* Create the threads */ for (i=0; i < nbr_threads * 2; i++) { CHECK( 0, pthread_create( &thr[i], NULL, test_fct, (i & 1) ? &td_1 : &td_2 ) ); } /* Synchronize everyone */ { int ret = pthread_barrier_wait(&bar); if (ret != PTHREAD_BARRIER_SERIAL_THREAD) { CHECK( 0, ret); } else { CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret); /* for trace only */ } } /* Now post all the messages */ for (i=0; i < NBR_MSG * nbr_threads * 2; i++) { msg = msgs[i]; CHECK( 0, fd_fifo_post(queue, &msg) ); } /* Join all threads. This blocks if messages are lost... */ for (i=0; i < nbr_threads * 2; i++) { CHECK( 0, pthread_join( thr[i], NULL ) ); } /* Check the count of the queue is back to 0 */ CHECK( 0, fd_fifo_length(queue) ); /* Destroy this queue and the messages */ CHECK( 0, fd_fifo_del(&queue) ); for (i=0; i < NBR_MSG * nbr_threads * 2; i++) { CHECK( 0, fd_msg_free( msgs[i] ) ); } } /* Test thread cancelation */ { struct fifo *queue = NULL; pthread_barrier_t bar; struct test_data td; pthread_t th; /* Create the queue */ CHECK( 0, fd_fifo_new(&queue, 0) ); /* Create the barrier */ CHECK( 0, pthread_barrier_init(&bar, NULL, 2) ); /* Initialize the ts */ CHECK(0, clock_gettime(CLOCK_REALTIME, &ts)); ts.tv_sec += 10; /* Set the timeout to 10 second */ /* Initialize the test data structures */ td.queue = queue; td.bar = &bar; td.ts = &ts; td.nbr = 1; /* Create the thread */ CHECK( 0, pthread_create( &th, NULL, test_fct, &td ) ); /* Wait for the thread to be running */ { int ret = pthread_barrier_wait(&bar); if (ret != PTHREAD_BARRIER_SERIAL_THREAD) { CHECK( 0, ret); } else { CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret ); } } /* Now cancel the thread */ CHECK( 0, pthread_cancel( th ) ); /* Join it */ CHECK( 0, pthread_join( th, NULL ) ); /* Do the same with the other function */ td.ts = NULL; /* Create the thread */ CHECK( 0, pthread_create( &th, NULL, test_fct, &td ) ); /* Wait for the thread to be running */ { int ret = pthread_barrier_wait(&bar); if (ret != PTHREAD_BARRIER_SERIAL_THREAD) { CHECK( 0, ret); } else { CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret ); } } /* Now cancel the thread */ CHECK( 0, pthread_cancel( th ) ); /* Join it */ CHECK( 0, pthread_join( th, NULL ) ); /* Destroy the queue */ CHECK( 0, fd_fifo_del(&queue) ); } /* Test the threashold function */ { struct fifo * queue = NULL; int i; struct msg * msg = NULL; /* Create the queue */ CHECK( 0, fd_fifo_new(&queue, 0) ); /* Prepare the test data */ memset(&thrh_td, 0, sizeof(thrh_td)); thrh_td.queue = queue; /* Set the thresholds for the queue */ CHECK( 0, fd_fifo_setthrhd ( queue, NULL, 6, thrh_cb_h, 4, thrh_cb_l ) ); /* Post 5 messages, no cb must be called. */ for (i=0; i<5; i++) { msg = msg1; CHECK( 0, fd_fifo_post(queue, &msg) ); } /* 5 msg in queue */ CHECK( 0, thrh_td.h_calls ); CHECK( 0, thrh_td.l_calls ); /* Get all these messages, and check again */ for (i=0; i<5; i++) { CHECK( 0, fd_fifo_get(queue, &msg) ); } /* 0 msg in queue */ CHECK( 0, thrh_td.h_calls ); CHECK( 0, thrh_td.l_calls ); /* Now, post 6 messages, the high threashold */ for (i=0; i<6; i++) { msg = msg1; CHECK( 0, fd_fifo_post(queue, &msg) ); } /* 6 msg in queue */ CHECK( 1, thrh_td.h_calls ); CHECK( 0, thrh_td.l_calls ); /* Remove 2 messages, to reach the low threshold */ for (i=0; i<2; i++) { CHECK( 0, fd_fifo_get(queue, &msg) ); } /* 4 msg in queue */ CHECK( 1, thrh_td.h_calls ); CHECK( 1, thrh_td.l_calls ); /* Come again at the high threshold */ for (i=0; i<2; i++) { msg = msg1; CHECK( 0, fd_fifo_post(queue, &msg) ); } /* 6 msg in queue */ CHECK( 2, thrh_td.h_calls ); CHECK( 1, thrh_td.l_calls ); /* Suppose the queue continues to grow */ for (i=0; i<6; i++) { msg = msg1; CHECK( 0, fd_fifo_post(queue, &msg) ); } /* 12 msg in queue */ CHECK( 3, thrh_td.h_calls ); CHECK( 1, thrh_td.l_calls ); for (i=0; i<5; i++) { msg = msg1; CHECK( 0, fd_fifo_post(queue, &msg) ); } /* 17 msg in queue */ CHECK( 3, thrh_td.h_calls ); CHECK( 1, thrh_td.l_calls ); /* Now the queue goes back to 0 messages */ for (i=0; i<17; i++) { CHECK( 0, fd_fifo_get(queue, &msg) ); } /* 0 msg in queue */ CHECK( 3, thrh_td.h_calls ); CHECK( 3, thrh_td.l_calls ); /* We're done for this test */ CHECK( 0, fd_fifo_del(&queue) ); } /* Test max queue limit */ { struct fifo *queue = NULL; struct test_data td; pthread_t th; int * item, i; /* Create the queue */ CHECK( 0, fd_fifo_new(&queue, 10) ); /* Initialize the test data structures */ td.queue = queue; td.nbr = 15; CHECK( 0, pthread_create( &th, NULL, test_fct2, &td ) ); usleep(100000); /* 100 millisec */ CHECK( 10, iter ); CHECK( 0, fd_fifo_tryget(queue, &item) ); CHECK( 0, *item); free(item); usleep(100000); /* 100 millisec */ CHECK( 11, iter ); for (i=1; i<4; i++) { CHECK( 0, fd_fifo_get(queue, &item) ); CHECK( i, *item); free(item); } usleep(100000); /* 100 millisec */ CHECK( 14, iter ); for (; i < td.nbr; i++) { CHECK( 0, fd_fifo_tryget(queue, &item) ); CHECK( i, *item); free(item); } CHECK( 0, pthread_join( th, NULL ) ); CHECK( 15, iter ); } /* Delete the messages */ CHECK( 0, fd_msg_free( msg1 ) ); CHECK( 0, fd_msg_free( msg2 ) ); CHECK( 0, fd_msg_free( msg3 ) ); /* That's all for the tests yet */ PASSTEST(); }