File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / tests / test-timer-correctness.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:12 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

    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>