Annotation of embedaddon/quagga/tests/test-timer-correctness.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Test program to verify that scheduled timers are executed in the
                      3:  * correct order.
                      4:  *
                      5:  * Copyright (C) 2013 by Open Source Routing.
                      6:  * Copyright (C) 2013 by Internet Systems Consortium, Inc. ("ISC")
                      7:  *
                      8:  * This file is part of Quagga
                      9:  *
                     10:  * Quagga is free software; you can redistribute it and/or modify it
                     11:  * under the terms of the GNU General Public License as published by the
                     12:  * Free Software Foundation; either version 2, or (at your option) any
                     13:  * later version.
                     14:  *
                     15:  * Quagga is distributed in the hope that it will be useful, but
                     16:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     17:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     18:  * General Public License for more details.
                     19:  *
                     20:  * You should have received a copy of the GNU General Public License
                     21:  * along with Quagga; see the file COPYING.  If not, write to the Free
                     22:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
                     23:  * 02111-1307, USA.
                     24:  */
                     25: 
                     26: #include <zebra.h>
                     27: 
                     28: #include <stdio.h>
                     29: #include <unistd.h>
                     30: 
                     31: #include "memory.h"
                     32: #include "pqueue.h"
                     33: #include "prng.h"
                     34: #include "thread.h"
                     35: 
                     36: #define SCHEDULE_TIMERS 800
                     37: #define REMOVE_TIMERS   200
                     38: 
                     39: #define TIMESTR_LEN strlen("4294967296.999999")
                     40: 
                     41: struct thread_master *master;
                     42: 
                     43: static size_t log_buf_len;
                     44: static size_t log_buf_pos;
                     45: static char *log_buf;
                     46: 
                     47: static size_t expected_buf_len;
                     48: static size_t expected_buf_pos;
                     49: static char *expected_buf;
                     50: 
                     51: static struct prng *prng;
                     52: 
                     53: static struct thread **timers;
                     54: 
                     55: static int timers_pending;
                     56: 
                     57: static void terminate_test(void)
                     58: {
                     59:   int exit_code;
                     60: 
                     61:   if (strcmp(log_buf, expected_buf))
                     62:     {
                     63:       fprintf(stderr, "Expected output and received output differ.\n");
                     64:       fprintf(stderr, "---Expected output: ---\n%s", expected_buf);
                     65:       fprintf(stderr, "---Actual output: ---\n%s", log_buf);
                     66:       exit_code = 1;
                     67:     }
                     68:   else
                     69:     {
                     70:       printf("Expected output and actual output match.\n");
                     71:       exit_code = 0;
                     72:     }
                     73: 
                     74:   thread_master_free(master);
                     75:   XFREE(MTYPE_TMP, log_buf);
                     76:   XFREE(MTYPE_TMP, expected_buf);
                     77:   prng_free(prng);
                     78:   XFREE(MTYPE_TMP, timers);
                     79: 
                     80:   exit(exit_code);
                     81: }
                     82: 
                     83: static int timer_func(struct thread *thread)
                     84: {
                     85:   int rv;
                     86: 
                     87:   rv = snprintf(log_buf + log_buf_pos, log_buf_len - log_buf_pos,
                     88:                 "%s\n", (char*)thread->arg);
                     89:   assert(rv >= 0);
                     90:   log_buf_pos += rv;
                     91:   assert(log_buf_pos < log_buf_len);
                     92:   XFREE(MTYPE_TMP, thread->arg);
                     93: 
                     94:   timers_pending--;
                     95:   if (!timers_pending)
                     96:     terminate_test();
                     97: 
                     98:   return 0;
                     99: }
                    100: 
                    101: static int cmp_timeval(const void* a, const void *b)
                    102: {
                    103:   const struct timeval *ta = *(struct timeval * const *)a;
                    104:   const struct timeval *tb = *(struct timeval * const *)b;
                    105: 
                    106:   if (timercmp(ta, tb, <))
                    107:     return -1;
                    108:   if (timercmp(ta, tb, >))
                    109:     return 1;
                    110:   return 0;
                    111: }
                    112: 
                    113: int main(int argc, char **argv)
                    114: {
                    115:   int i, j;
                    116:   struct thread t;
                    117:   struct timeval **alarms;
                    118: 
                    119:   master = thread_master_create();
                    120: 
                    121:   log_buf_len = SCHEDULE_TIMERS * (TIMESTR_LEN + 1) + 1;
                    122:   log_buf_pos = 0;
                    123:   log_buf = XMALLOC(MTYPE_TMP, log_buf_len);
                    124: 
                    125:   expected_buf_len = SCHEDULE_TIMERS * (TIMESTR_LEN + 1) + 1;
                    126:   expected_buf_pos = 0;
                    127:   expected_buf = XMALLOC(MTYPE_TMP, expected_buf_len);
                    128: 
                    129:   prng = prng_new(0);
                    130: 
                    131:   timers = XMALLOC(MTYPE_TMP, SCHEDULE_TIMERS * sizeof(*timers));
                    132: 
                    133:   for (i = 0; i < SCHEDULE_TIMERS; i++)
                    134:     {
                    135:       long interval_msec;
                    136:       int ret;
                    137:       char *arg;
                    138: 
                    139:       /* Schedule timers to expire in 0..5 seconds */
                    140:       interval_msec = prng_rand(prng) % 5000;
                    141:       arg = XMALLOC(MTYPE_TMP, TIMESTR_LEN + 1);
                    142:       timers[i] = thread_add_timer_msec(master, timer_func, arg, interval_msec);
                    143:       ret = snprintf(arg, TIMESTR_LEN + 1, "%lld.%06lld",
                    144:                      (long long)timers[i]->u.sands.tv_sec,
                    145:                      (long long)timers[i]->u.sands.tv_usec);
                    146:       assert(ret > 0);
                    147:       assert((size_t)ret < TIMESTR_LEN + 1);
                    148:       timers_pending++;
                    149:     }
                    150: 
                    151:   for (i = 0; i < REMOVE_TIMERS; i++)
                    152:     {
                    153:       int index;
                    154: 
                    155:       index = prng_rand(prng) % SCHEDULE_TIMERS;
                    156:       if (!timers[index])
                    157:         continue;
                    158: 
                    159:       XFREE(MTYPE_TMP, timers[index]->arg);
                    160:       thread_cancel(timers[index]);
                    161:       timers[index] = NULL;
                    162:       timers_pending--;
                    163:     }
                    164: 
                    165:   /* We create an array of pointers to the alarm times and sort
                    166:    * that array. That sorted array is used to generate a string
                    167:    * representing the expected "output" of the timers when they
                    168:    * are run. */
                    169:   j = 0;
                    170:   alarms = XMALLOC(MTYPE_TMP, timers_pending * sizeof(*alarms));
                    171:   for (i = 0; i < SCHEDULE_TIMERS; i++)
                    172:     {
                    173:       if (!timers[i])
                    174:         continue;
                    175:       alarms[j++] = &timers[i]->u.sands;
                    176:     }
                    177:   qsort(alarms, j, sizeof(*alarms), cmp_timeval);
                    178:   for (i = 0; i < j; i++)
                    179:     {
                    180:       int ret;
                    181: 
                    182:       ret = snprintf(expected_buf + expected_buf_pos,
                    183:                      expected_buf_len - expected_buf_pos,
                    184:                      "%lld.%06lld\n",
                    185:                      (long long)alarms[i]->tv_sec,
                    186:                      (long long)alarms[i]->tv_usec);
                    187:       assert(ret > 0);
                    188:       expected_buf_pos += ret;
                    189:       assert(expected_buf_pos < expected_buf_len);
                    190:     }
                    191:   XFREE(MTYPE_TMP, alarms);
                    192: 
                    193:   while (thread_fetch(master, &t))
                    194:     thread_call(&t);
                    195: 
                    196:   return 0;
                    197: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>