1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc. See LICENSE. */ 2#include <assert.h> 3#include <stdio.h> 4#include <stdlib.h> 5#include <string.h> 6#ifndef WIN32 7#include <sys/time.h> 8#endif 9 10#include "lsquic.h" 11#include "lsquic_types.h" 12#include "lsquic_alarmset.h" 13#include "lsquic_parse.h" 14 15static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_035); 16 17 18struct goaway_parse_test { 19 int lineno; 20 unsigned char buf[0x100]; 21 size_t buf_len; 22 uint32_t error_code; 23 uint32_t last_stream_id; 24 uint16_t reason_len; 25 const char *reason; 26 int retval; 27}; 28 29static const struct goaway_parse_test parse_tests[] = { 30 31 { 32 .lineno = __LINE__, 33 .buf = { 0x03, 0x31, 0x00, 0x00, 0x00, 0x34, 0x12, 0x00, 0x00, 0x05, 0x00, 'D', 'u', 'd', 'e', '!', }, 34 .buf_len = 0x100, 35 .error_code = 0x31, 36 .last_stream_id = 0x1234, 37 .reason_len = 0x05, 38 .reason = "Dude!", 39 .retval = 11 + 5, 40 }, 41 42 { 43 .lineno = __LINE__, 44 .buf = { 0x03, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 'D', 'u', 'd', 'e', '!', }, 45 .buf_len = 8, /* Too short #1 */ 46 .error_code = 0x31, 47 .last_stream_id = 0x1234, 48 .reason_len = 0x05, 49 .reason = "Dude!", 50 .retval = -1, 51 }, 52 53 { 54 .lineno = __LINE__, 55 .buf = { 0x03, 0x31, 0x00, 0x00, 0x00, 0x34, 0x12, 0x00, 0x00, 0x05, 0x00, 'D', 'u', 'd', 'e', '!', }, 56 .buf_len = 12, /* Too short #2 */ 57 .error_code = 0x31, 58 .last_stream_id = 0x1234, 59 .reason_len = 0x05, 60 .reason = "Dude!", 61 .retval = -2, 62 }, 63 64 { .buf = { 0 }, } 65}; 66 67 68struct goaway_gen_test { 69 int lineno; 70 uint32_t error_code; 71 uint32_t last_stream_id; 72 const char *reason; 73 int retval; 74 unsigned char buf[0x100]; 75 size_t buf_len; 76}; 77 78 79static const struct goaway_gen_test gen_tests[] = { 80 81 { 82 .lineno = __LINE__, 83 .error_code = 0x12345678, 84 .last_stream_id = 0x1234, 85 .reason = "Dude, where is my car?", 86 .retval = 11 + sizeof("Dude, where is my car?") - 1, 87 .buf_len = 0x100, 88 .buf = { 89 0x03, 90 0x78, 0x56, 0x34, 0x12, 91 0x34, 0x12, 0x00, 0x00, 92 sizeof("Dude, where is my car?") - 1, 0x00, 93 'D', 'u', 'd', 'e', ',', ' ', 'w', 'h', 'e', 'r', 'e', ' ', 'i', 's', ' ', 'm', 'y', ' ', 'c', 'a', 'r', '?', 94 }, 95 }, 96 97 { 98 .lineno = __LINE__, 99 .error_code = 0x12345678, 100 .last_stream_id = 0x2345, 101 .reason = NULL, 102 .retval = 11, 103 .buf_len = 0x100, 104 .buf = { 105 0x02, 106 0x78, 0x56, 0x34, 0x12, 107 0x45, 0x23, 0x00, 0x00, 108 0x00, 0x00, /* Zero-sized string */ 109 }, 110 }, 111 112 { 113 .lineno = __LINE__, 114 .error_code = 0x12345678, 115 .last_stream_id = 0x2345, 116 .reason = "Dude, where is my car?", 117 .retval = -1, /* Too short */ 118 .buf_len = 0x10, 119 }, 120 121 { .buf = { 0 }, } 122 123}; 124 125 126static void 127run_parse_tests (void) 128{ 129 const struct goaway_parse_test *test; 130 for (test = parse_tests; test->buf[0]; ++test) 131 { 132 uint32_t error_code = ~0; 133 uint32_t last_stream_id = ~0; 134 uint16_t reason_len = ~0; 135 const char *reason; 136 int sz = pf->pf_parse_goaway_frame(test->buf, test->buf_len, 137 &error_code, &last_stream_id, &reason_len, &reason); 138 assert(sz == test->retval); 139 if (0 == sz) 140 { 141 assert(test->error_code == error_code); 142 assert(test->last_stream_id == last_stream_id); 143 assert(test->reason_len == reason_len); 144 assert(0 == memcmp(test->reason, reason, reason_len)); 145 } 146 } 147} 148 149 150static void 151run_gen_tests (void) 152{ 153 const struct goaway_gen_test *test; 154 for (test = gen_tests; test->buf[0]; ++test) 155 { 156 unsigned char buf[0x100]; 157 int sz = pf->pf_gen_goaway_frame(buf, sizeof(buf), 158 test->error_code, test->last_stream_id, test->reason, 159 test->reason ? strlen(test->reason) : 0); 160 assert(sz == test->retval); 161 if (0 == sz) 162 assert(0 == memcmp(test->buf, buf, sz)); 163 } 164} 165 166 167int 168main (void) 169{ 170 run_parse_tests(); 171 run_gen_tests(); 172 return 0; 173} 174