1/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 2#include <assert.h> 3#include <stdlib.h> 4#include <sys/queue.h> 5 6#include "lsquic.h" 7#include "lsquic_types.h" 8#include "lsquic_int_types.h" 9#include "lsquic_attq.h" 10#include "lsquic_hash.h" 11#include "lsquic_conn.h" 12 13 14static char curiosity[] = 15 "Dogs say cats love too much, are irresponsible," 16 "are changeable, marry too many wives," 17 "desert their children, chill all dinner tables" 18 "with tales of their nine lives." 19 "Well, they are lucky. Let them be" 20 "nine-lived and contradictory," 21 "curious enough to change, prepared to pay" 22 "the cat price, which is to die" 23 "and die again and again," 24 "each time with no less pain." 25 "A cat minority of one" 26 "is all that can be counted on" 27 "to tell the truth. And what cats have to tell" 28 "on each return from hell" 29 "is this: that dying is what the living do," 30 "that dying is what the loving do," 31 "and that dead dogs are those who do not know" 32 "that dying is what, to live, each has to do." 33 ; 34 35 36static int 37cmp_chars_asc (const void *ap, const void *bp) 38{ 39 char a = * (char *) ap; 40 char b = * (char *) bp; 41 return (a > b) - (b > a); 42} 43 44 45static int 46cmp_chars_desc (const void *ap, const void *bp) 47{ 48 char a = * (char *) ap; 49 char b = * (char *) bp; 50 return (a < b) - (b < a); 51} 52 53 54enum sort_action { SORT_NONE, SORT_ASC, SORT_DESC, }; 55 56static void 57test_attq_ordering (enum sort_action sa) 58{ 59 struct attq *q; 60 struct lsquic_conn *conns, *conn; 61 const struct attq_elem *next_attq; 62 lsquic_time_t prev; 63 lsquic_time_t t; 64 unsigned i; 65 int s; 66 67 switch (sa) 68 { 69 case SORT_NONE: 70 break; 71 case SORT_ASC: 72 qsort(curiosity, sizeof(curiosity) * 73 sizeof(curiosity[0]), sizeof(curiosity[0]), cmp_chars_asc); 74 break; 75 case SORT_DESC: 76 qsort(curiosity, sizeof(curiosity) * 77 sizeof(curiosity[0]), sizeof(curiosity[0]), cmp_chars_desc); 78 break; 79 } 80 81 q = lsquic_attq_create(); 82 83 for (i = 0; i < sizeof(curiosity); ++i) 84 { 85 unsigned count_before = lsquic_attq_count_before(q, curiosity[i]); 86 assert(count_before == 0); 87 } 88 89 conns = calloc(sizeof(curiosity), sizeof(conns[0])); 90 for (i = 0; i < sizeof(curiosity); ++i) 91 { 92 s = lsquic_attq_add(q, &conns[i], (lsquic_time_t) curiosity[i], 0); 93 assert(s == 0); 94 } 95 96 for (i = 0; i < sizeof(curiosity); ++i) 97 assert(conns[i].cn_attq_elem); 98 99 if (sa == SORT_ASC) 100 { 101 unsigned counts[ sizeof(curiosity) ]; 102 unsigned count_before; 103 counts[0] = 0; 104 for (i = 1; i < sizeof(curiosity); ++i) 105 { 106 if (curiosity[i - 1] == curiosity[i]) 107 counts[i] = counts[i - 1]; 108 else 109 counts[i] = i; 110 } 111 for (i = 1; i < sizeof(curiosity); ++i) 112 { 113 count_before = lsquic_attq_count_before(q, curiosity[i]); 114 assert(count_before == counts[i]); 115 } 116 } 117 118#ifdef _MSC_VER 119 prev = 0; 120#endif 121 for (i = 0; i < sizeof(curiosity); ++i) 122 { 123 next_attq = lsquic_attq_next(q); 124 assert(next_attq); 125 t = next_attq->ae_adv_time; 126 if (i > 0) 127 assert(t >= prev); 128 prev = t; 129 conn = lsquic_attq_pop(q, ~0ULL); 130 assert(conn); 131 } 132 133 next_attq = lsquic_attq_next(q); 134 assert(!next_attq); 135 conn = lsquic_attq_pop(q, ~0ULL); 136 assert(!conn); 137 138 free(conns); 139 lsquic_attq_destroy(q); 140} 141 142 143/* Filter up */ 144static void 145test_attq_removal_1 (void) 146{ 147 struct attq *q; 148 struct lsquic_conn *conns; 149 150 q = lsquic_attq_create(); 151 conns = calloc(6, sizeof(conns[0])); 152 153 lsquic_attq_add(q, &conns[0], 1, 0); 154 lsquic_attq_add(q, &conns[1], 4, 0); 155 lsquic_attq_add(q, &conns[2], 2, 0); 156 lsquic_attq_add(q, &conns[3], 5, 0); 157 lsquic_attq_add(q, &conns[4], 6, 0); 158 lsquic_attq_add(q, &conns[5], 3, 0); 159 160 lsquic_attq_remove(q, &conns[3]); 161 162 free(conns); 163 lsquic_attq_destroy(q); 164} 165 166 167/* Filter down */ 168static void 169test_attq_removal_2 (void) 170{ 171 struct attq *q; 172 struct lsquic_conn *conns; 173 174 q = lsquic_attq_create(); 175 conns = calloc(9, sizeof(conns[0])); 176 177 lsquic_attq_add(q, &conns[0], 1, 0); 178 lsquic_attq_add(q, &conns[1], 5, 0); 179 lsquic_attq_add(q, &conns[2], 6, 0); 180 lsquic_attq_add(q, &conns[3], 9, 0); 181 lsquic_attq_add(q, &conns[4], 11, 0); 182 lsquic_attq_add(q, &conns[5], 8, 0); 183 lsquic_attq_add(q, &conns[6], 15, 0); 184 lsquic_attq_add(q, &conns[7], 17, 0); 185 lsquic_attq_add(q, &conns[8], 21, 0); 186 187 lsquic_attq_remove(q, &conns[1]); 188 189 free(conns); 190 lsquic_attq_destroy(q); 191} 192 193 194/* Filter up */ 195static void 196test_attq_removal_3 (void) 197{ 198 struct attq *q; 199 struct lsquic_conn *conns; 200 201 q = lsquic_attq_create(); 202 conns = calloc(9, sizeof(conns[0])); 203 204 lsquic_attq_add(q, &conns[0], 1, 0); 205 lsquic_attq_add(q, &conns[1], 9, 0); 206 lsquic_attq_add(q, &conns[2], 22, 0); 207 lsquic_attq_add(q, &conns[3], 17, 0); 208 lsquic_attq_add(q, &conns[4], 11, 0); 209 lsquic_attq_add(q, &conns[5], 33, 0); 210 lsquic_attq_add(q, &conns[6], 27, 0); 211 lsquic_attq_add(q, &conns[7], 21, 0); 212 lsquic_attq_add(q, &conns[8], 19, 0); 213 214 lsquic_attq_remove(q, &conns[1]); 215 216 free(conns); 217 lsquic_attq_destroy(q); 218} 219 220 221int 222main (void) 223{ 224 test_attq_ordering(SORT_NONE); 225 test_attq_ordering(SORT_ASC); 226 test_attq_ordering(SORT_DESC); 227 test_attq_removal_1(); 228 test_attq_removal_2(); 229 test_attq_removal_3(); 230 return 0; 231} 232