1/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 2#include <assert.h> 3#include <stdio.h> 4#include <stdlib.h> 5#include <string.h> 6#include <sys/queue.h> 7 8#include "lsquic.h" 9 10#include "lsquic_packet_common.h" 11#include "lsquic_alarmset.h" 12 13 14static lsquic_time_t global_now; 15 16static struct cb_ctx { 17 lsquic_time_t last_expiry; 18 unsigned n_calls; 19} global_ctx; 20 21 22static void 23alarm_cb (enum alarm_id al_id, void *ctx, lsquic_time_t expiry, 24 lsquic_time_t now) 25{ 26 struct cb_ctx *cb_ctx = ctx; 27 assert(cb_ctx == &global_ctx); 28 assert(cb_ctx->last_expiry <= expiry); /* This checks sortedness */ 29 assert(global_now == now); 30 ++cb_ctx->n_calls; 31 cb_ctx->last_expiry = expiry; 32} 33 34 35#if __GNUC__ 36# define popcount __builtin_popcount 37#else 38static int 39popcount (unsigned v) 40{ 41 int count, i; 42 for (i = 0, count = 0; i < sizeof(v) * 8; ++i) 43 if (v & (1 << i)) 44 ++count; 45 return count; 46} 47#endif 48 49 50int 51main (void) 52{ 53 unsigned i; 54 lsquic_alarmset_t alset; 55 56 lsquic_alarmset_init(&alset, 0); 57 58 for (i = 0; i < MAX_LSQUIC_ALARMS; ++i) 59 lsquic_alarmset_init_alarm(&alset, i, alarm_cb, &global_ctx); 60 61 lsquic_alarmset_set(&alset, 0, 20); 62 lsquic_alarmset_set(&alset, 1, 5); 63 lsquic_alarmset_set(&alset, 2, 11); 64 lsquic_alarmset_set(&alset, 3, 15); 65 66 assert(lsquic_alarmset_is_set(&alset, 3)); 67 lsquic_alarmset_unset(&alset, 3); 68 assert(!lsquic_alarmset_is_set(&alset, 3)); 69 lsquic_alarmset_set(&alset, 3, 15); 70 71 global_ctx.last_expiry = 0; 72 global_ctx.n_calls = 0; 73 74 lsquic_alarmset_ring_expired(&alset, global_now = 1); 75 76 assert(0 == global_ctx.n_calls); 77 78 assert(lsquic_alarmset_is_set(&alset, 1)); 79 lsquic_alarmset_ring_expired(&alset, global_now = 10); 80 assert(!lsquic_alarmset_is_set(&alset, 1)); 81 82 assert(1 == global_ctx.n_calls); 83 assert(5 == global_ctx.last_expiry); 84 85 lsquic_alarmset_ring_expired(&alset, global_now = 12); 86 87 assert(2 == global_ctx.n_calls); 88 assert(11 == global_ctx.last_expiry); 89 90 lsquic_alarmset_ring_expired(&alset, global_now = 20); 91 92 /* expiry must be strictly smaller than current time */ 93 assert(3 == global_ctx.n_calls); 94 assert(15 == global_ctx.last_expiry); 95 96 lsquic_alarmset_ring_expired(&alset, global_now = 21); 97 98 assert(4 == global_ctx.n_calls); 99 assert(20 == global_ctx.last_expiry); 100 101 unsigned t = 1; 102 for (i = 1; i < (1u << MAX_LSQUIC_ALARMS); ++i) 103 { 104 alset.as_armed_set = 0; /* Unset all */ 105 unsigned const count = popcount(i); 106 unsigned const min_n = i % count; 107 unsigned const min_t = t++; 108 unsigned j, n; 109 enum alarm_id ids[2]; 110 for (j = 0, n = 0; j < MAX_LSQUIC_ALARMS; ++j) 111 { 112 if ((1u << j) & i) 113 { 114 if (n == min_n) 115 { 116 ids[0] = j; 117 lsquic_alarmset_set(&alset, j, min_t); 118 } 119 else 120 lsquic_alarmset_set(&alset, j, t++); 121 ++n; 122 } 123 } 124 lsquic_time_t found_min_t = lsquic_alarmset_mintime(&alset, &ids[1]); 125 assert(min_t == found_min_t); 126 assert(ids[0] == ids[1]); 127 } 128 129 return 0; 130} 131