test_ack.c revision a74702c6
1/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 2/* Test both generation and parsing of IETF ACK frames */ 3 4#include <assert.h> 5#include <string.h> 6 7#include "lsquic.h" 8#include "lsquic_types.h" 9#include "lsquic_int_types.h" 10#include "lsquic_sizes.h" 11#include "lsquic_parse.h" 12#include "lsquic_trans_params.h" 13 14struct test 15{ 16 int lineno; 17 int skip_gen; 18 19 struct ack_info acki; 20 21 size_t encoded_sz; 22 unsigned char encoded[0x1000]; 23}; 24 25static const lsquic_time_t now = 0x12345676890; 26 27static const struct test tests[] = 28{ 29 { 30 .lineno = __LINE__, 31 .acki = 32 { 33 .n_ranges = 2, 34 .lack_delta = 0xFEDCB0, 35 .ranges = 36 { 37 [0] = { 7, 7, }, 38 [1] = { 0, 0, }, 39 }, 40 }, 41 .encoded = 42 { 43 /* Type */ 0x02, 44 /* Largest acked */ 0x07, 45 /* ACK delay */ 0x80, 0x1F, 0xDB, 0x96, 46 /* Addl block count */ 0x01, 47 /* First ACK block */ 0x00, 48 /* Gap */ 0x05, 49 /* ACK block */ 0x00, 50 }, 51 .encoded_sz = 10, 52 }, 53 54 { 55 .lineno = __LINE__, 56 .acki = 57 { 58 .n_ranges = 3, 59 .lack_delta = 0xFEDCB0, 60 .ranges = 61 { 62 [0] = { 10, 10, }, 63 [1] = { 7, 7, }, 64 [2] = { 0, 0, }, 65 }, 66 }, 67 .encoded = 68 { 69 /* Type */ 0x02, 70 /* Largest acked */ 10, 71 /* ACK delay */ 0x80, 0x1F, 0xDB, 0x96, 72 /* Addl block count */ 2, 73 /* First ACK block */ 0x00, 74 /* Gap */ 0x01, 75 /* ACK block */ 0x00, 76 /* Gap */ 0x05, 77 /* ACK block */ 0x00, 78 }, 79 .encoded_sz = 12, 80 }, 81 82 { 83 .lineno = __LINE__, 84 .acki = 85 { 86 .flags = AI_ECN, 87 .n_ranges = 3, 88 .lack_delta = 0xFEDCB0, 89 .ecn_counts = { 0, 0x010203, 1, 0x49, }, 90 .ranges = 91 { 92 [0] = { 10, 10, }, 93 [1] = { 7, 7, }, 94 [2] = { 0, 0, }, 95 }, 96 }, 97 .encoded = 98 { 99 /* Type */ 0x03, 100 /* Largest acked */ 10, 101 /* ACK delay */ 0x80, 0x1F, 0xDB, 0x96, 102 /* Addl block count */ 2, 103 /* First ACK block */ 0x00, 104 /* Gap */ 0x01, 105 /* ACK block */ 0x00, 106 /* Gap */ 0x05, 107 /* ACK block */ 0x00, 108 /* ECT(1) count */ 0x01, 109 /* ECT(0) count */ 0x80, 0x01, 0x02, 0x03, 110 /* ECN-CE count */ 0x40, 0x49, 111 }, 112 .encoded_sz = 19, 113 }, 114 115}; 116 117struct rechist 118{ 119 const struct ack_info *acki; 120 unsigned next_range; 121}; 122 123 124static const struct lsquic_packno_range * 125rechist_next (void *ctx) 126{ 127 struct rechist *rechist = ctx; 128 if (rechist->next_range < rechist->acki->n_ranges) 129 return rechist->acki->ranges + rechist->next_range++; 130 else 131 return NULL; 132} 133 134static const struct lsquic_packno_range * 135rechist_first (void *ctx) 136{ 137 struct rechist *rechist = ctx; 138 rechist->next_range = 0; 139 return rechist_next(rechist); 140} 141 142static lsquic_time_t 143rechist_largest_recv (void *ctx) 144{ 145 struct rechist *rechist = ctx; 146 return now - rechist->acki->lack_delta; 147} 148 149 150static void 151compare_ackis (const struct ack_info *exp, const struct ack_info *got) 152{ 153 unsigned i; 154 155 assert(exp->flags == got->flags); 156 assert(exp->n_ranges == got->n_ranges); 157 assert(exp->lack_delta == got->lack_delta); 158 159 for (i = 0; i < exp->n_ranges; ++i) 160 { 161 assert(exp->ranges[i].high == got->ranges[i].high); 162 assert(exp->ranges[i].low == got->ranges[i].low); 163 } 164 165 if (exp->flags & AI_ECN) 166 for (i = 1; i <= 3; ++i) 167 assert(exp->ecn_counts[i] == got->ecn_counts[i]); 168} 169 170 171static void 172run_test (const struct test *test) 173{ 174 int len, has_missing; 175 lsquic_packno_t largest_received; 176 const struct parse_funcs *pf; 177 struct rechist rechist; 178 struct ack_info acki; 179 size_t sz; 180 unsigned char buf[0x1000]; 181 182 pf = select_pf_by_ver(LSQVER_ID27); 183 if (!test->skip_gen) 184 { 185 rechist.acki = &test->acki; 186 len = pf->pf_gen_ack_frame(buf, sizeof(buf), rechist_first, rechist_next, 187 rechist_largest_recv, &rechist, now, &has_missing, &largest_received, 188 test->acki.flags & AI_ECN ? rechist.acki->ecn_counts : NULL); 189 assert(len > 0); 190 assert(largest_received == largest_acked(&test->acki)); 191 assert((size_t) len == test->encoded_sz); 192 assert(0 == memcmp(test->encoded, buf, test->encoded_sz)); 193 } 194 195 /* Test that shorter buffers cannot get parsed */ 196 for (sz = 1; sz < test->encoded_sz; ++sz) 197 { 198 len = pf->pf_parse_ack_frame(test->encoded, sz, &acki, 199 TP_DEF_ACK_DELAY_EXP); 200 assert(len < 0); 201 } 202 203 len = pf->pf_parse_ack_frame(test->encoded, sizeof(test->encoded), &acki, 204 TP_DEF_ACK_DELAY_EXP); 205 assert(len > 0); 206 assert((size_t) len == test->encoded_sz); 207 compare_ackis(&test->acki, &acki); 208} 209 210int 211main (void) 212{ 213 const struct test *test; 214 215 for (test = tests; test < tests + sizeof(tests) / sizeof(tests[0]); ++test) 216 run_test(test); 217 218 return 0; 219} 220