143a63c18SDmitri Tikhonov/* 243a63c18SDmitri Tikhonov * Test QPACK. 343a63c18SDmitri Tikhonov */ 443a63c18SDmitri Tikhonov 543a63c18SDmitri Tikhonov#include <assert.h> 6147b1758SDmitri Tikhonov#include <ctype.h> 743a63c18SDmitri Tikhonov#include <stdint.h> 843a63c18SDmitri Tikhonov#include <stdio.h> 943a63c18SDmitri Tikhonov#include <stdlib.h> 1043a63c18SDmitri Tikhonov#include <string.h> 1143a63c18SDmitri Tikhonov 1243a63c18SDmitri Tikhonov#include "lsqpack.h" 13b43d0c9bSDmitri Tikhonov#include "lsqpack-test.h" 1460620859SDmitri Tikhonov#include "lsxpack_header.h" 1543a63c18SDmitri Tikhonov 1643a63c18SDmitri Tikhonov#define ENC_BUF_SZ 200 1743a63c18SDmitri Tikhonov#define HEADER_BUF_SZ 200 1843a63c18SDmitri Tikhonov#define PREFIX_BUF_SZ 10 1943a63c18SDmitri Tikhonov 2043a63c18SDmitri Tikhonovstatic const struct qpack_header_block_test 2143a63c18SDmitri Tikhonov{ 2243a63c18SDmitri Tikhonov /* Identification: */ 2343a63c18SDmitri Tikhonov int qhbt_lineno; 2443a63c18SDmitri Tikhonov 2543a63c18SDmitri Tikhonov /* Input: */ 266b87e695SDmitri Tikhonov unsigned qhbt_table_size; 276b87e695SDmitri Tikhonov unsigned qhbt_max_risked_streams; 2843a63c18SDmitri Tikhonov unsigned qhbt_n_headers; 2943a63c18SDmitri Tikhonov struct { 3043a63c18SDmitri Tikhonov const char *name, *value; 31051fed2dSDmitri Tikhonov enum lsqpack_enc_flags flags; 3243a63c18SDmitri Tikhonov } qhbt_headers[10]; 3343a63c18SDmitri Tikhonov 3443a63c18SDmitri Tikhonov /* Output: */ 3543a63c18SDmitri Tikhonov size_t qhbt_enc_sz; 3643a63c18SDmitri Tikhonov unsigned char qhbt_enc_buf[ENC_BUF_SZ]; 3743a63c18SDmitri Tikhonov 3843a63c18SDmitri Tikhonov size_t qhbt_prefix_sz; 3943a63c18SDmitri Tikhonov unsigned char qhbt_prefix_buf[PREFIX_BUF_SZ]; 4043a63c18SDmitri Tikhonov 4143a63c18SDmitri Tikhonov size_t qhbt_header_sz; 4243a63c18SDmitri Tikhonov unsigned char qhbt_header_buf[HEADER_BUF_SZ]; 4343a63c18SDmitri Tikhonov} header_block_tests[] = 4443a63c18SDmitri Tikhonov{ 45051fed2dSDmitri Tikhonov 4643a63c18SDmitri Tikhonov { 4743a63c18SDmitri Tikhonov .qhbt_lineno = __LINE__, 486db915e7SDmitri Tikhonov .qhbt_table_size = 0x1000, 496db915e7SDmitri Tikhonov .qhbt_max_risked_streams = 100, 5043a63c18SDmitri Tikhonov .qhbt_n_headers = 1, 5143a63c18SDmitri Tikhonov .qhbt_headers = { 52051fed2dSDmitri Tikhonov { ":method", "GET", 0, }, 5343a63c18SDmitri Tikhonov }, 5443a63c18SDmitri Tikhonov .qhbt_enc_sz = 0, 5543a63c18SDmitri Tikhonov .qhbt_prefix_sz = 2, 5643a63c18SDmitri Tikhonov .qhbt_prefix_buf = "\x00\x00", 5743a63c18SDmitri Tikhonov .qhbt_header_sz = 1, 5843a63c18SDmitri Tikhonov .qhbt_header_buf = { 59c0da112cSDmitri Tikhonov 0x80 | 0x40 | 17, 6043a63c18SDmitri Tikhonov }, 6143a63c18SDmitri Tikhonov }, 62051fed2dSDmitri Tikhonov 63051fed2dSDmitri Tikhonov { 64051fed2dSDmitri Tikhonov .qhbt_lineno = __LINE__, 656db915e7SDmitri Tikhonov .qhbt_table_size = 0x1000, 666db915e7SDmitri Tikhonov .qhbt_max_risked_streams = 100, 67051fed2dSDmitri Tikhonov .qhbt_n_headers = 1, 68051fed2dSDmitri Tikhonov .qhbt_headers = { 6977647c9cSDmitri Tikhonov { ":method", "method", LQEF_NEVER_INDEX, }, 70051fed2dSDmitri Tikhonov }, 71051fed2dSDmitri Tikhonov .qhbt_enc_sz = 0, 72051fed2dSDmitri Tikhonov .qhbt_prefix_sz = 2, 73051fed2dSDmitri Tikhonov .qhbt_prefix_buf = "\x00\x00", 74c0da112cSDmitri Tikhonov .qhbt_header_sz = 8, 75051fed2dSDmitri Tikhonov .qhbt_header_buf = { 76c0da112cSDmitri Tikhonov 0x40 | 0x20 | 0x10 | 0x0F, 0x00, 77051fed2dSDmitri Tikhonov 0x80 /* Huffman */ | 5 /* length */, 7895bacc9fSDmitri Tikhonov 0xa4, 0xa9, 0x9c, 0xf2, 0x7f, 79051fed2dSDmitri Tikhonov }, 80051fed2dSDmitri Tikhonov }, 81051fed2dSDmitri Tikhonov 826b87e695SDmitri Tikhonov { 836b87e695SDmitri Tikhonov .qhbt_lineno = __LINE__, 846db915e7SDmitri Tikhonov .qhbt_table_size = 0x1000, 856b87e695SDmitri Tikhonov .qhbt_max_risked_streams = 0, 866b87e695SDmitri Tikhonov .qhbt_n_headers = 1, 876b87e695SDmitri Tikhonov .qhbt_headers = { 886b87e695SDmitri Tikhonov { ":method", "method", 0, }, 896b87e695SDmitri Tikhonov }, 9095bacc9fSDmitri Tikhonov .qhbt_enc_sz = 7, 916b87e695SDmitri Tikhonov .qhbt_enc_buf = { 92c0da112cSDmitri Tikhonov 0x80 | 0x40 /* static */ | 15 /* name index */, 936b87e695SDmitri Tikhonov 0x80 /* Huffman */ | 5 /* length */, 9495bacc9fSDmitri Tikhonov 0xa4, 0xa9, 0x9c, 0xf2, 0x7f, 956b87e695SDmitri Tikhonov }, 966b87e695SDmitri Tikhonov .qhbt_prefix_sz = 2, 976b87e695SDmitri Tikhonov .qhbt_prefix_buf = "\x00\x00", 98c0da112cSDmitri Tikhonov .qhbt_header_sz = 8, 996b87e695SDmitri Tikhonov .qhbt_header_buf = { 100c0da112cSDmitri Tikhonov 0x40 | 0x10 /* Static */ | 15, 0x00, 1016b87e695SDmitri Tikhonov 0x80 /* Huffman */ | 5 /* length */, 10295bacc9fSDmitri Tikhonov 0xa4, 0xa9, 0x9c, 0xf2, 0x7f, 10395bacc9fSDmitri Tikhonov }, 10495bacc9fSDmitri Tikhonov }, 10595bacc9fSDmitri Tikhonov 10695bacc9fSDmitri Tikhonov { 10795bacc9fSDmitri Tikhonov .qhbt_lineno = __LINE__, 1086db915e7SDmitri Tikhonov .qhbt_table_size = 0x1000, 1096db915e7SDmitri Tikhonov .qhbt_max_risked_streams = 0x1000, 11095bacc9fSDmitri Tikhonov .qhbt_n_headers = 1, 11195bacc9fSDmitri Tikhonov .qhbt_headers = { 11295bacc9fSDmitri Tikhonov { ":method", "method", 0, }, 11395bacc9fSDmitri Tikhonov }, 11495bacc9fSDmitri Tikhonov .qhbt_enc_sz = 7, 11595bacc9fSDmitri Tikhonov .qhbt_enc_buf = { 116c0da112cSDmitri Tikhonov 0x80 | 0x40 /* static */ | 15 /* name index */, 11795bacc9fSDmitri Tikhonov 0x80 /* Huffman */ | 5 /* length */, 11895bacc9fSDmitri Tikhonov 0xa4, 0xa9, 0x9c, 0xf2, 0x7f, 11995bacc9fSDmitri Tikhonov }, 12095bacc9fSDmitri Tikhonov .qhbt_prefix_sz = 2, 121205a2804SDmitri Tikhonov .qhbt_prefix_buf = { 0x02, 0x80, }, 12295bacc9fSDmitri Tikhonov .qhbt_header_sz = 1, 12395bacc9fSDmitri Tikhonov .qhbt_header_buf = { 124c9e9d2cdSDmitri Tikhonov 0x10 | 0 /* Relative dynamic ID */, 1256b87e695SDmitri Tikhonov }, 1266b87e695SDmitri Tikhonov }, 1276b87e695SDmitri Tikhonov 1286ac74e8cSDmitri Tikhonov { 1296ac74e8cSDmitri Tikhonov .qhbt_lineno = __LINE__, 1306db915e7SDmitri Tikhonov .qhbt_table_size = 0x1000, 1316db915e7SDmitri Tikhonov .qhbt_max_risked_streams = 0x1000, 1326ac74e8cSDmitri Tikhonov .qhbt_n_headers = 1, 1336ac74e8cSDmitri Tikhonov .qhbt_headers = { 13477647c9cSDmitri Tikhonov { "dude", "where is my car?", LQEF_NEVER_INDEX, }, 1356ac74e8cSDmitri Tikhonov }, 1366ac74e8cSDmitri Tikhonov .qhbt_enc_sz = 0, 1376ac74e8cSDmitri Tikhonov .qhbt_prefix_sz = 2, 1386ac74e8cSDmitri Tikhonov .qhbt_prefix_buf = "\x00\x00", 1396ac74e8cSDmitri Tikhonov .qhbt_header_sz = 17, 1406ac74e8cSDmitri Tikhonov .qhbt_header_buf = { 14146a42218SDmitri Tikhonov 0x20 | 0x10 /* No index */ | 0x08 | 3, 14246a42218SDmitri Tikhonov 0x92, 0xd9, 0x0b, 14346a42218SDmitri Tikhonov 0x80 | 0xC, 14446a42218SDmitri Tikhonov 0xf1, 0x39, 0x6c, 0x2a, 0x86, 0x42, 0x94, 0xfa, 14546a42218SDmitri Tikhonov 0x50, 0x83, 0xb3, 0xfc, 14646a42218SDmitri Tikhonov }, 14746a42218SDmitri Tikhonov }, 14846a42218SDmitri Tikhonov 14946a42218SDmitri Tikhonov { 15046a42218SDmitri Tikhonov .qhbt_lineno = __LINE__, 1516db915e7SDmitri Tikhonov .qhbt_table_size = 0x1000, 15246a42218SDmitri Tikhonov .qhbt_max_risked_streams = 0, 1539413d779SDmitri Tikhonov .qhbt_n_headers = 3, 15446a42218SDmitri Tikhonov .qhbt_headers = { 15546a42218SDmitri Tikhonov { "dude", "where is my car?", 0, }, 15618555864SDmitri Tikhonov { ":method", "GET", 0, }, 1579413d779SDmitri Tikhonov /* The "aaa..." string triggers header_out_grow_buf() */ 1589413d779SDmitri Tikhonov { "aaaaaaaaaaaaaaaaaaaaaaaaaa", 1599413d779SDmitri Tikhonov "aaaaaaaaaaaaaaaaaaaaaaaaaa", 0, }, 16046a42218SDmitri Tikhonov }, 1619413d779SDmitri Tikhonov .qhbt_enc_sz = 53, 16246a42218SDmitri Tikhonov .qhbt_enc_buf = { 16346a42218SDmitri Tikhonov 0x40 | 0x20 | 3, 16446a42218SDmitri Tikhonov 0x92, 0xd9, 0x0b, 16546a42218SDmitri Tikhonov 0x80 | 0xC, 16646a42218SDmitri Tikhonov 0xf1, 0x39, 0x6c, 0x2a, 0x86, 0x42, 0x94, 0xfa, 16746a42218SDmitri Tikhonov 0x50, 0x83, 0xb3, 0xfc, 1689413d779SDmitri Tikhonov 0x40 /* Without name reference */ | 0x20 /* Huffman */ | 17 /* Length */, 1699413d779SDmitri Tikhonov 0x18, 0xc6, 0x31, 0x8c, 0x63, 0x18, 0xc6, 0x31, 0x8c, 1709413d779SDmitri Tikhonov 0x63, 0x18, 0xc6, 0x31, 0x8c, 0x63, 0x18, 0xff, 1719413d779SDmitri Tikhonov 0x80 /* Huffman */ | 17 /* length */, 1729413d779SDmitri Tikhonov 0x18, 0xc6, 0x31, 0x8c, 0x63, 0x18, 0xc6, 0x31, 0x8c, 1739413d779SDmitri Tikhonov 0x63, 0x18, 0xc6, 0x31, 0x8c, 0x63, 0x18, 0xff, 17446a42218SDmitri Tikhonov }, 17546a42218SDmitri Tikhonov .qhbt_prefix_sz = 2, 17646a42218SDmitri Tikhonov .qhbt_prefix_buf = "\x00\x00", 1779413d779SDmitri Tikhonov .qhbt_header_sz = 55, 17846a42218SDmitri Tikhonov .qhbt_header_buf = { 17946a42218SDmitri Tikhonov 0x20 | 0x08 | 3, 1806ac74e8cSDmitri Tikhonov 0x92, 0xd9, 0x0b, 1816ac74e8cSDmitri Tikhonov 0x80 | 0xC, 1826ac74e8cSDmitri Tikhonov 0xf1, 0x39, 0x6c, 0x2a, 0x86, 0x42, 0x94, 0xfa, 1836ac74e8cSDmitri Tikhonov 0x50, 0x83, 0xb3, 0xfc, 18418555864SDmitri Tikhonov 0x80 | 0x40 | 17, 1859413d779SDmitri Tikhonov 0x20 /* Without name reference */ | 0x08 /* Huffman */ | 7 , 0x0A /* Length */, 1869413d779SDmitri Tikhonov 0x18, 0xc6, 0x31, 0x8c, 0x63, 0x18, 0xc6, 0x31, 0x8c, 1879413d779SDmitri Tikhonov 0x63, 0x18, 0xc6, 0x31, 0x8c, 0x63, 0x18, 0xff, 1889413d779SDmitri Tikhonov 0x80 /* Huffman */ | 17 /* length */, 1899413d779SDmitri Tikhonov 0x18, 0xc6, 0x31, 0x8c, 0x63, 0x18, 0xc6, 0x31, 0x8c, 1909413d779SDmitri Tikhonov 0x63, 0x18, 0xc6, 0x31, 0x8c, 0x63, 0x18, 0xff, 1916ac74e8cSDmitri Tikhonov }, 1926ac74e8cSDmitri Tikhonov }, 1936ac74e8cSDmitri Tikhonov 1948e76c09eSDmitri Tikhonov { 1958e76c09eSDmitri Tikhonov .qhbt_lineno = __LINE__, 1966db915e7SDmitri Tikhonov .qhbt_table_size = 0x1000, 1978e76c09eSDmitri Tikhonov .qhbt_max_risked_streams = 1, 1988e76c09eSDmitri Tikhonov .qhbt_n_headers = 1, 1998e76c09eSDmitri Tikhonov .qhbt_headers = { 2008e76c09eSDmitri Tikhonov { "dude", "where is my car?", 0, }, 2018e76c09eSDmitri Tikhonov }, 2028e76c09eSDmitri Tikhonov .qhbt_enc_sz = 17, 2038e76c09eSDmitri Tikhonov .qhbt_enc_buf = { 2048e76c09eSDmitri Tikhonov 0x40 | 0x20 | 3, 2058e76c09eSDmitri Tikhonov 0x92, 0xd9, 0x0b, 2068e76c09eSDmitri Tikhonov 0x80 | 0xC, 2078e76c09eSDmitri Tikhonov 0xf1, 0x39, 0x6c, 0x2a, 0x86, 0x42, 0x94, 0xfa, 2088e76c09eSDmitri Tikhonov 0x50, 0x83, 0xb3, 0xfc, 2098e76c09eSDmitri Tikhonov }, 2108e76c09eSDmitri Tikhonov .qhbt_prefix_sz = 2, 211205a2804SDmitri Tikhonov .qhbt_prefix_buf = { 0x02, 0x80, }, 2128e76c09eSDmitri Tikhonov .qhbt_header_sz = 1, 2138e76c09eSDmitri Tikhonov .qhbt_header_buf = { 214c9e9d2cdSDmitri Tikhonov 0x10 | 0 /* Relative dynamic ID */, 2158e76c09eSDmitri Tikhonov }, 2168e76c09eSDmitri Tikhonov }, 2178e76c09eSDmitri Tikhonov 21843a63c18SDmitri Tikhonov}; 21943a63c18SDmitri Tikhonov 22043a63c18SDmitri Tikhonov 2219e982dfdSDmitri Tikhonovstruct header_buf 2229e982dfdSDmitri Tikhonov{ 2239e982dfdSDmitri Tikhonov unsigned off; 2249e982dfdSDmitri Tikhonov char buf[UINT16_MAX]; 2259e982dfdSDmitri Tikhonov}; 2269e982dfdSDmitri Tikhonov 2279e982dfdSDmitri Tikhonov 2289e982dfdSDmitri Tikhonovint 2299e982dfdSDmitri Tikhonovheader_set_ptr (struct lsxpack_header *hdr, struct header_buf *header_buf, 2309e982dfdSDmitri Tikhonov const char *name, size_t name_len, 2319e982dfdSDmitri Tikhonov const char *val, size_t val_len) 2329e982dfdSDmitri Tikhonov{ 2339e982dfdSDmitri Tikhonov if (header_buf->off + name_len + val_len <= sizeof(header_buf->buf)) 2349e982dfdSDmitri Tikhonov { 2359e982dfdSDmitri Tikhonov memcpy(header_buf->buf + header_buf->off, name, name_len); 2369e982dfdSDmitri Tikhonov memcpy(header_buf->buf + header_buf->off + name_len, val, val_len); 2379e982dfdSDmitri Tikhonov lsxpack_header_set_offset2(hdr, header_buf->buf + header_buf->off, 2389e982dfdSDmitri Tikhonov 0, name_len, name_len, val_len); 2399e982dfdSDmitri Tikhonov header_buf->off += name_len + val_len; 2409e982dfdSDmitri Tikhonov return 0; 2419e982dfdSDmitri Tikhonov } 2429e982dfdSDmitri Tikhonov else 2439e982dfdSDmitri Tikhonov return -1; 2449e982dfdSDmitri Tikhonov} 2459e982dfdSDmitri Tikhonov 24643a63c18SDmitri Tikhonovstatic void 24743a63c18SDmitri Tikhonovrun_header_test (const struct qpack_header_block_test *test) 24843a63c18SDmitri Tikhonov{ 24943a63c18SDmitri Tikhonov unsigned char header_buf[HEADER_BUF_SZ], enc_buf[ENC_BUF_SZ], 25043a63c18SDmitri Tikhonov prefix_buf[PREFIX_BUF_SZ]; 25195bacc9fSDmitri Tikhonov unsigned header_off, enc_off; 252b43d0c9bSDmitri Tikhonov size_t header_sz, enc_sz, dec_sz; 25343a63c18SDmitri Tikhonov struct lsqpack_enc enc; 25443a63c18SDmitri Tikhonov unsigned i; 25543a63c18SDmitri Tikhonov size_t nw; 25643a63c18SDmitri Tikhonov int s; 25743a63c18SDmitri Tikhonov enum lsqpack_enc_status enc_st; 25825170ed8SStephen Petrides float ratio; 259a122a7bdSDmitri Tikhonov unsigned char dec_buf[LSQPACK_LONGEST_SDTC]; 26060620859SDmitri Tikhonov struct lsxpack_header xhdr; 2619e982dfdSDmitri Tikhonov struct header_buf hbuf; 26243a63c18SDmitri Tikhonov 263b43d0c9bSDmitri Tikhonov dec_sz = sizeof(dec_buf); 2646686ad13SDmitri Tikhonov s = lsqpack_enc_init(&enc, stderr, test->qhbt_table_size, 2656686ad13SDmitri Tikhonov test->qhbt_table_size, test->qhbt_max_risked_streams, 266b43d0c9bSDmitri Tikhonov LSQPACK_ENC_OPT_IX_AGGR, dec_buf, &dec_sz); 26743a63c18SDmitri Tikhonov assert(s == 0); 26843a63c18SDmitri Tikhonov 26943a63c18SDmitri Tikhonov s = lsqpack_enc_start_header(&enc, 0, 0); 27043a63c18SDmitri Tikhonov assert(s == 0); 27143a63c18SDmitri Tikhonov 27243a63c18SDmitri Tikhonov header_off = 0, enc_off = 0; 27343a63c18SDmitri Tikhonov for (i = 0; i < test->qhbt_n_headers; ++i) 27443a63c18SDmitri Tikhonov { 27588967572SDmitri Tikhonov /* Increase buffers one by one to exercise error conditions */ 27688967572SDmitri Tikhonov enc_sz = 0; 27788967572SDmitri Tikhonov header_sz = 0; 27888967572SDmitri Tikhonov while (1) 27988967572SDmitri Tikhonov { 2809e982dfdSDmitri Tikhonov hbuf.off = 0; 2819e982dfdSDmitri Tikhonov s = header_set_ptr(&xhdr, &hbuf, 28288967572SDmitri Tikhonov test->qhbt_headers[i].name, 28388967572SDmitri Tikhonov strlen(test->qhbt_headers[i].name), 28488967572SDmitri Tikhonov test->qhbt_headers[i].value, 28560620859SDmitri Tikhonov strlen(test->qhbt_headers[i].value)); 2869e982dfdSDmitri Tikhonov assert(s == 0); 28760620859SDmitri Tikhonov enc_st = lsqpack_enc_encode(&enc, 28860620859SDmitri Tikhonov enc_buf + enc_off, &enc_sz, 28960620859SDmitri Tikhonov header_buf + header_off, &header_sz, 29060620859SDmitri Tikhonov &xhdr, 29188967572SDmitri Tikhonov test->qhbt_headers[i].flags); 29288967572SDmitri Tikhonov switch (enc_st) 29388967572SDmitri Tikhonov { 29488967572SDmitri Tikhonov case LQES_NOBUF_ENC: 29588967572SDmitri Tikhonov if (enc_sz < sizeof(enc_buf) - enc_off) 29688967572SDmitri Tikhonov ++enc_sz; 29788967572SDmitri Tikhonov else 29888967572SDmitri Tikhonov assert(0); 29988967572SDmitri Tikhonov break; 30088967572SDmitri Tikhonov case LQES_NOBUF_HEAD: 30188967572SDmitri Tikhonov if (header_sz < sizeof(header_buf) - header_off) 30288967572SDmitri Tikhonov ++header_sz; 30388967572SDmitri Tikhonov else 30488967572SDmitri Tikhonov assert(0); 30588967572SDmitri Tikhonov break; 30688967572SDmitri Tikhonov default: 30788967572SDmitri Tikhonov assert(enc_st == LQES_OK); 30888967572SDmitri Tikhonov goto end_encode_one_header; 30988967572SDmitri Tikhonov } 31088967572SDmitri Tikhonov } 31188967572SDmitri Tikhonov end_encode_one_header: 31243a63c18SDmitri Tikhonov enc_off += enc_sz; 31343a63c18SDmitri Tikhonov header_off += header_sz; 31443a63c18SDmitri Tikhonov } 31543a63c18SDmitri Tikhonov 3163ce33568SDmitri Tikhonov nw = lsqpack_enc_end_header(&enc, prefix_buf, sizeof(prefix_buf), NULL); 31743a63c18SDmitri Tikhonov assert(nw == test->qhbt_prefix_sz); 31843a63c18SDmitri Tikhonov assert(0 == memcmp(test->qhbt_prefix_buf, prefix_buf, nw)); 31995bacc9fSDmitri Tikhonov assert(enc_off == test->qhbt_enc_sz); 32095bacc9fSDmitri Tikhonov assert(0 == memcmp(test->qhbt_enc_buf, enc_buf, enc_off)); 32195bacc9fSDmitri Tikhonov assert(header_off == test->qhbt_header_sz); 32295bacc9fSDmitri Tikhonov assert(0 == memcmp(test->qhbt_header_buf, header_buf, header_off)); 32325170ed8SStephen Petrides assert(lsqpack_enc_ratio(&enc) > 0.0); 32443a63c18SDmitri Tikhonov 32543a63c18SDmitri Tikhonov lsqpack_enc_cleanup(&enc); 32643a63c18SDmitri Tikhonov} 32743a63c18SDmitri Tikhonov 32818555864SDmitri Tikhonov 32918555864SDmitri Tikhonovstruct dhte /* decoded header test ext */ 33018555864SDmitri Tikhonov{ 33118555864SDmitri Tikhonov struct lsxpack_header xhdr; 33218555864SDmitri Tikhonov size_t buf_off; 33318555864SDmitri Tikhonov char buf[0x1000]; 33418555864SDmitri Tikhonov}; 33518555864SDmitri Tikhonov 33618555864SDmitri Tikhonov 33718555864SDmitri Tikhonovstatic void 33818555864SDmitri Tikhonovdht_unblocked (void *hblock_ctx_p) 33918555864SDmitri Tikhonov{ 34018555864SDmitri Tikhonov assert(0); /* Not expecting this to be called */ 34118555864SDmitri Tikhonov} 34218555864SDmitri Tikhonov 34318555864SDmitri Tikhonov 34418555864SDmitri Tikhonovstatic struct lsxpack_header * 34518555864SDmitri Tikhonovdht_prepare_decode (void *hblock_ctx_p, struct lsxpack_header *xhdr, size_t space) 34618555864SDmitri Tikhonov{ 34718555864SDmitri Tikhonov struct dhte *const dhte = hblock_ctx_p; 34818555864SDmitri Tikhonov size_t avail; 34918555864SDmitri Tikhonov 35018555864SDmitri Tikhonov if (space > LSXPACK_MAX_STRLEN) 35118555864SDmitri Tikhonov return NULL; 35218555864SDmitri Tikhonov 35318555864SDmitri Tikhonov if (xhdr) 35418555864SDmitri Tikhonov { 35518555864SDmitri Tikhonov assert(xhdr == &dhte->xhdr); 35618555864SDmitri Tikhonov assert(xhdr->val_len < space); 35718555864SDmitri Tikhonov avail = sizeof(dhte->buf) - xhdr->name_offset - 1 /* NUL */; 35818555864SDmitri Tikhonov if (avail < space) 35918555864SDmitri Tikhonov return NULL; 36018555864SDmitri Tikhonov xhdr->val_len = space; 36118555864SDmitri Tikhonov } 36218555864SDmitri Tikhonov else 36318555864SDmitri Tikhonov { 36418555864SDmitri Tikhonov avail = sizeof(dhte->buf) - dhte->buf_off - 1 /* NUL */; 36518555864SDmitri Tikhonov if (avail < space) 36618555864SDmitri Tikhonov return NULL; 36718555864SDmitri Tikhonov lsxpack_header_prepare_decode(&dhte->xhdr, dhte->buf, dhte->buf_off, 36818555864SDmitri Tikhonov space); 36918555864SDmitri Tikhonov } 37018555864SDmitri Tikhonov 37118555864SDmitri Tikhonov return &dhte->xhdr; 37218555864SDmitri Tikhonov} 37318555864SDmitri Tikhonov 37418555864SDmitri Tikhonov 37518555864SDmitri Tikhonovstatic int 37618555864SDmitri Tikhonovdht_process_header (void *hblock_ctx_p, struct lsxpack_header *xhdr) 37718555864SDmitri Tikhonov{ 37818555864SDmitri Tikhonov struct dhte *const dhte = hblock_ctx_p; 37918555864SDmitri Tikhonov 38018555864SDmitri Tikhonov assert(xhdr == &dhte->xhdr); 38118555864SDmitri Tikhonov dhte->buf_off += lsxpack_header_get_dec_size(xhdr); 38218555864SDmitri Tikhonov 38318555864SDmitri Tikhonov return 0; 38418555864SDmitri Tikhonov} 38518555864SDmitri Tikhonov 38618555864SDmitri Tikhonov 38718555864SDmitri Tikhonovstatic void 38818555864SDmitri Tikhonovrun_decoded_headers_test_ext (const struct qpack_header_block_test *test, 38918555864SDmitri Tikhonov const enum lsqpack_dec_opts opts, const size_t name_offset) 39018555864SDmitri Tikhonov{ 39118555864SDmitri Tikhonov struct lsqpack_dec dec; 39218555864SDmitri Tikhonov char exp_hbuf[0x1000]; /* Large enough to hold all headers */ 39318555864SDmitri Tikhonov struct dhte dhte; 39418555864SDmitri Tikhonov size_t sz; 39518555864SDmitri Tikhonov unsigned i; 39618555864SDmitri Tikhonov int s; 39718555864SDmitri Tikhonov enum lsqpack_read_header_status rhs; 39818555864SDmitri Tikhonov const unsigned char *buf; 39918555864SDmitri Tikhonov unsigned char dec_buf[LSQPACK_LONGEST_HEADER_ACK]; 40018555864SDmitri Tikhonov size_t dec_sz; 40118555864SDmitri Tikhonov const struct lsqpack_dec_hset_if dht_if = { 40218555864SDmitri Tikhonov .dhi_unblocked = dht_unblocked, 40318555864SDmitri Tikhonov .dhi_prepare_decode = dht_prepare_decode, 40418555864SDmitri Tikhonov .dhi_process_header = dht_process_header, 40518555864SDmitri Tikhonov }; 40618555864SDmitri Tikhonov 40718555864SDmitri Tikhonov /* Construct expected headers buffer: */ 40818555864SDmitri Tikhonov sz = 0; 40918555864SDmitri Tikhonov exp_hbuf[0] = '\0'; 41018555864SDmitri Tikhonov for (i = 0; i < test->qhbt_n_headers; ++i) 41118555864SDmitri Tikhonov { 41218555864SDmitri Tikhonov strcpy(exp_hbuf + sz, test->qhbt_headers[i].name); 41318555864SDmitri Tikhonov sz += strlen(test->qhbt_headers[i].name); 41418555864SDmitri Tikhonov if (opts & LSQPACK_DEC_OPT_HTTP1X) 41518555864SDmitri Tikhonov { 41618555864SDmitri Tikhonov strcpy(exp_hbuf + sz, ": "); 41718555864SDmitri Tikhonov sz += 2; 41818555864SDmitri Tikhonov } 41918555864SDmitri Tikhonov strcpy(exp_hbuf + sz, test->qhbt_headers[i].value); 42018555864SDmitri Tikhonov sz += strlen(test->qhbt_headers[i].value); 42118555864SDmitri Tikhonov if (opts & LSQPACK_DEC_OPT_HTTP1X) 42218555864SDmitri Tikhonov { 42318555864SDmitri Tikhonov strcpy(exp_hbuf + sz, "\r\n"); 42418555864SDmitri Tikhonov sz += 2; 42518555864SDmitri Tikhonov } 42618555864SDmitri Tikhonov } 42718555864SDmitri Tikhonov assert(sz < sizeof(exp_hbuf)); /* Self-check */ 42818555864SDmitri Tikhonov 42918555864SDmitri Tikhonov /* Decode headers into dhte buffer */ 43018555864SDmitri Tikhonov dhte.buf_off = name_offset; 43118555864SDmitri Tikhonov lsqpack_dec_init(&dec, NULL, test->qhbt_table_size, 43218555864SDmitri Tikhonov test->qhbt_max_risked_streams, &dht_if, opts); 43318555864SDmitri Tikhonov if (test->qhbt_enc_sz) 43418555864SDmitri Tikhonov { 43518555864SDmitri Tikhonov s = lsqpack_dec_enc_in(&dec, test->qhbt_enc_buf, test->qhbt_enc_sz); 43618555864SDmitri Tikhonov assert(s == 0); 43718555864SDmitri Tikhonov } 43818555864SDmitri Tikhonov assert(test->qhbt_header_sz); /* Self-check */ 43918555864SDmitri Tikhonov buf = test->qhbt_prefix_buf; 44018555864SDmitri Tikhonov dec_sz = sizeof(dec_buf); 44118555864SDmitri Tikhonov rhs = lsqpack_dec_header_in(&dec, &dhte, 0, 44218555864SDmitri Tikhonov test->qhbt_prefix_sz + test->qhbt_header_sz, 44318555864SDmitri Tikhonov &buf, test->qhbt_prefix_sz, 44418555864SDmitri Tikhonov dec_buf, &dec_sz); 44518555864SDmitri Tikhonov assert(rhs == LQRHS_NEED); 44618555864SDmitri Tikhonov assert(buf == test->qhbt_prefix_buf + test->qhbt_prefix_sz); 44718555864SDmitri Tikhonov buf = test->qhbt_header_buf; 44818555864SDmitri Tikhonov dec_sz = sizeof(dec_buf); 44918555864SDmitri Tikhonov rhs = lsqpack_dec_header_read(&dec, &dhte, 45018555864SDmitri Tikhonov &buf, test->qhbt_header_sz, 45118555864SDmitri Tikhonov dec_buf, &dec_sz); 45218555864SDmitri Tikhonov assert(rhs == LQRHS_DONE); 45318555864SDmitri Tikhonov assert(buf == test->qhbt_header_buf + test->qhbt_header_sz); 45418555864SDmitri Tikhonov lsqpack_dec_cleanup(&dec); 45518555864SDmitri Tikhonov 45618555864SDmitri Tikhonov /* Now compare the buffers */ 45718555864SDmitri Tikhonov dhte.buf[dhte.buf_off] = '\0'; 45818555864SDmitri Tikhonov s = strcmp(dhte.buf + name_offset, exp_hbuf); 45918555864SDmitri Tikhonov assert(s == 0); 46018555864SDmitri Tikhonov} 46118555864SDmitri Tikhonov 46218555864SDmitri Tikhonov 46318555864SDmitri Tikhonovstatic void 46418555864SDmitri Tikhonovrun_decoded_headers_test (const struct qpack_header_block_test *test) 46518555864SDmitri Tikhonov{ 46618555864SDmitri Tikhonov const enum lsqpack_dec_opts opts[] = { 0, LSQPACK_DEC_OPT_HTTP1X, }; 46718555864SDmitri Tikhonov const size_t offs[] = { 0, 1, 20, }; 46818555864SDmitri Tikhonov unsigned i, j; 46918555864SDmitri Tikhonov 47018555864SDmitri Tikhonov for (i = 0; i < sizeof(opts) / sizeof(opts[0]); ++i) 47118555864SDmitri Tikhonov for (j = 0; j < sizeof(offs) / sizeof(offs[0]); ++j) 47218555864SDmitri Tikhonov run_decoded_headers_test_ext(test, opts[i], offs[j]); 47318555864SDmitri Tikhonov} 47418555864SDmitri Tikhonov 47518555864SDmitri Tikhonov 476d4822b2bSDaan De Meyerstatic void 477d4822b2bSDaan De Meyerrun_header_cancellation_test(const struct qpack_header_block_test *test) { 478d4822b2bSDaan De Meyer unsigned char header_buf[HEADER_BUF_SZ]; 479d4822b2bSDaan De Meyer size_t header_sz, enc_sz; 480d4822b2bSDaan De Meyer struct lsqpack_enc enc; 481d4822b2bSDaan De Meyer int s; 482d4822b2bSDaan De Meyer enum lsqpack_enc_status enc_st; 48360620859SDmitri Tikhonov struct lsxpack_header xhdr; 4849e982dfdSDmitri Tikhonov struct header_buf hbuf; 485d4822b2bSDaan De Meyer 486d4822b2bSDaan De Meyer s = lsqpack_enc_init(&enc, stderr, 0, 0, test->qhbt_max_risked_streams, 487d4822b2bSDaan De Meyer LSQPACK_ENC_OPT_IX_AGGR, NULL, NULL); 488d4822b2bSDaan De Meyer assert(s == 0); 489d4822b2bSDaan De Meyer 490d4822b2bSDaan De Meyer s = lsqpack_enc_start_header(&enc, 0, 0); 491d4822b2bSDaan De Meyer assert(s == 0); 492d4822b2bSDaan De Meyer 493d4822b2bSDaan De Meyer header_sz = HEADER_BUF_SZ; 494d4822b2bSDaan De Meyer enc_sz = 0; 495d4822b2bSDaan De Meyer 4969e982dfdSDmitri Tikhonov hbuf.off = 0; 4979e982dfdSDmitri Tikhonov header_set_ptr(&xhdr, &hbuf, 49860620859SDmitri Tikhonov test->qhbt_headers[0].name, 49960620859SDmitri Tikhonov strlen(test->qhbt_headers[0].name), 50060620859SDmitri Tikhonov test->qhbt_headers[0].value, 50160620859SDmitri Tikhonov strlen(test->qhbt_headers[0].value)); 502d4822b2bSDaan De Meyer enc_st = lsqpack_enc_encode(&enc, 503d4822b2bSDaan De Meyer NULL, &enc_sz, 504d4822b2bSDaan De Meyer header_buf, &header_sz, 50560620859SDmitri Tikhonov &xhdr, 506d4822b2bSDaan De Meyer 0); 507d4822b2bSDaan De Meyer assert(enc_st == LQES_OK); 508d4822b2bSDaan De Meyer 509d4822b2bSDaan De Meyer s = lsqpack_enc_cancel_header(&enc); 510d4822b2bSDaan De Meyer assert(s == 0); 511d4822b2bSDaan De Meyer 512d4822b2bSDaan De Meyer /* Check that we can start again after cancelling. */ 513d4822b2bSDaan De Meyer s = lsqpack_enc_start_header(&enc, 0, 0); 514d4822b2bSDaan De Meyer assert(s == 0); 515d4822b2bSDaan De Meyer 516d4822b2bSDaan De Meyer lsqpack_enc_cleanup(&enc); 517d4822b2bSDaan De Meyer} 518d4822b2bSDaan De Meyer 51943a63c18SDmitri Tikhonov 520b43d0c9bSDmitri Tikhonovstatic void 521b43d0c9bSDmitri Tikhonovtest_enc_init (void) 522b43d0c9bSDmitri Tikhonov{ 523b43d0c9bSDmitri Tikhonov struct lsqpack_enc enc; 524b43d0c9bSDmitri Tikhonov size_t dec_sz; 525b43d0c9bSDmitri Tikhonov int s; 526b43d0c9bSDmitri Tikhonov unsigned i; 527b43d0c9bSDmitri Tikhonov const unsigned char *p; 528b43d0c9bSDmitri Tikhonov uint64_t val; 529b43d0c9bSDmitri Tikhonov struct lsqpack_dec_int_state state; 530a122a7bdSDmitri Tikhonov unsigned char dec_buf[LSQPACK_LONGEST_SDTC]; 531b43d0c9bSDmitri Tikhonov 532b43d0c9bSDmitri Tikhonov const struct { 533b43d0c9bSDmitri Tikhonov unsigned peer_max_size; /* Value provided by peer */ 534b43d0c9bSDmitri Tikhonov unsigned our_max_size; /* Value to use */ 535b43d0c9bSDmitri Tikhonov int expected_tsu; /* Expecting TSU instruction? */ 536b43d0c9bSDmitri Tikhonov } tests[] = { 537b43d0c9bSDmitri Tikhonov { 0x1000, 0x1000, 1, }, 538b43d0c9bSDmitri Tikhonov { 0x1000, 1, 1, }, 539b43d0c9bSDmitri Tikhonov { 0x100, 0x100, 1, }, 540b43d0c9bSDmitri Tikhonov { 0x1000, 0, 0, }, 541b43d0c9bSDmitri Tikhonov }; 542b43d0c9bSDmitri Tikhonov 543b43d0c9bSDmitri Tikhonov for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) 544b43d0c9bSDmitri Tikhonov { 545b43d0c9bSDmitri Tikhonov dec_sz = sizeof(dec_buf); 546b43d0c9bSDmitri Tikhonov s = lsqpack_enc_init(&enc, stderr, tests[i].peer_max_size, 547b43d0c9bSDmitri Tikhonov tests[i].our_max_size, 0, 0, dec_buf, &dec_sz); 548b43d0c9bSDmitri Tikhonov assert(s == 0); 549b43d0c9bSDmitri Tikhonov if (tests[i].expected_tsu) 550b43d0c9bSDmitri Tikhonov { 551b43d0c9bSDmitri Tikhonov assert(dec_sz > 0); 552b43d0c9bSDmitri Tikhonov assert((dec_buf[0] & 0xE0) == 0x20); 553b43d0c9bSDmitri Tikhonov p = dec_buf; 554d3cc03d7SDmitri Tikhonov state.resume = 0; 555b43d0c9bSDmitri Tikhonov s = lsqpack_dec_int(&p, p + dec_sz, 5, &val, &state); 556b43d0c9bSDmitri Tikhonov assert(s == 0); 557b43d0c9bSDmitri Tikhonov assert(val == tests[i].our_max_size); 558b43d0c9bSDmitri Tikhonov } 559b43d0c9bSDmitri Tikhonov else 560b43d0c9bSDmitri Tikhonov assert(dec_sz == 0); 561b43d0c9bSDmitri Tikhonov lsqpack_enc_cleanup(&enc); 562b43d0c9bSDmitri Tikhonov } 563b43d0c9bSDmitri Tikhonov} 564b43d0c9bSDmitri Tikhonov 565b43d0c9bSDmitri Tikhonov 56602c4e282SDmitri Tikhonov/* Test that push promise header does not use the dynamic table, nor does 56702c4e282SDmitri Tikhonov * it update history. 56802c4e282SDmitri Tikhonov */ 56902c4e282SDmitri Tikhonovstatic void 57002c4e282SDmitri Tikhonovtest_push_promise (void) 57102c4e282SDmitri Tikhonov{ 57202c4e282SDmitri Tikhonov struct lsqpack_enc enc; 57302c4e282SDmitri Tikhonov ssize_t nw; 57402c4e282SDmitri Tikhonov enum lsqpack_enc_status enc_st; 57502c4e282SDmitri Tikhonov int s; 57602c4e282SDmitri Tikhonov unsigned i; 57702c4e282SDmitri Tikhonov const unsigned char *p; 57802c4e282SDmitri Tikhonov uint64_t val; 57902c4e282SDmitri Tikhonov struct lsqpack_dec_int_state state; 580a122a7bdSDmitri Tikhonov unsigned char dec_buf[LSQPACK_LONGEST_SDTC]; 58102c4e282SDmitri Tikhonov unsigned char header_buf[HEADER_BUF_SZ], enc_buf[ENC_BUF_SZ], 58202c4e282SDmitri Tikhonov prefix_buf[PREFIX_BUF_SZ]; 58302c4e282SDmitri Tikhonov size_t header_sz, enc_sz, dec_sz; 5843ce33568SDmitri Tikhonov enum lsqpack_enc_header_flags hflags; 58560620859SDmitri Tikhonov struct lsxpack_header xhdr; 5869e982dfdSDmitri Tikhonov struct header_buf hbuf; 58702c4e282SDmitri Tikhonov 588c8a0661fSDmitri Tikhonov dec_sz = sizeof(dec_buf); 58902c4e282SDmitri Tikhonov s = lsqpack_enc_init(&enc, stderr, 0x1000, 0x1000, 100, 0, dec_buf, &dec_sz); 59002c4e282SDmitri Tikhonov assert(0 == s); 59102c4e282SDmitri Tikhonov 59202c4e282SDmitri Tikhonov (void) dec_sz; /* We don't care for this test */ 59302c4e282SDmitri Tikhonov 59402c4e282SDmitri Tikhonov s = lsqpack_enc_start_header(&enc, 0, 0); 59502c4e282SDmitri Tikhonov assert(0 == s); 59602c4e282SDmitri Tikhonov enc_sz = sizeof(enc_buf); 59702c4e282SDmitri Tikhonov header_sz = sizeof(header_buf); 5989e982dfdSDmitri Tikhonov hbuf.off = 0; 5999e982dfdSDmitri Tikhonov header_set_ptr(&xhdr, &hbuf, ":method", 7, "dude!", 5); 60002c4e282SDmitri Tikhonov enc_st = lsqpack_enc_encode(&enc, 60102c4e282SDmitri Tikhonov enc_buf, &enc_sz, header_buf, &header_sz, 60260620859SDmitri Tikhonov &xhdr, 0); 60302c4e282SDmitri Tikhonov assert(LQES_OK == enc_st); 60402c4e282SDmitri Tikhonov enc_sz = sizeof(enc_buf); 60502c4e282SDmitri Tikhonov header_sz = sizeof(header_buf); 6069e982dfdSDmitri Tikhonov header_set_ptr(&xhdr, &hbuf, ":method", 7, "dude!", 5); 60702c4e282SDmitri Tikhonov enc_st = lsqpack_enc_encode(&enc, 60802c4e282SDmitri Tikhonov enc_buf, &enc_sz, header_buf, &header_sz, 60960620859SDmitri Tikhonov &xhdr, 0); 61002c4e282SDmitri Tikhonov assert(LQES_OK == enc_st); 6113ce33568SDmitri Tikhonov nw = lsqpack_enc_end_header(&enc, prefix_buf, sizeof(prefix_buf), &hflags); 61202c4e282SDmitri Tikhonov assert(2 == nw); 61302c4e282SDmitri Tikhonov assert(!(prefix_buf[0] == 0 && prefix_buf[1] == 0)); /* Dynamic table used */ 6143ce33568SDmitri Tikhonov assert(hflags & LSQECH_REF_NEW_ENTRIES); 6153ce33568SDmitri Tikhonov assert(hflags & LSQECH_REF_AT_RISK); 61602c4e282SDmitri Tikhonov 61702c4e282SDmitri Tikhonov s = lsqpack_enc_start_header(&enc, 0, 0); 61802c4e282SDmitri Tikhonov assert(0 == s); 61902c4e282SDmitri Tikhonov enc_sz = sizeof(enc_buf); 62002c4e282SDmitri Tikhonov header_sz = sizeof(header_buf); 6219e982dfdSDmitri Tikhonov header_set_ptr(&xhdr, &hbuf, ":method", 7, "dude!", 5); 62202c4e282SDmitri Tikhonov enc_st = lsqpack_enc_encode(&enc, 62302c4e282SDmitri Tikhonov enc_buf, &enc_sz, header_buf, &header_sz, 62460620859SDmitri Tikhonov &xhdr, LQEF_NO_HIST_UPD|LQEF_NO_DYN); 62502c4e282SDmitri Tikhonov assert(LQES_OK == enc_st); 62602c4e282SDmitri Tikhonov enc_sz = sizeof(enc_buf); 62702c4e282SDmitri Tikhonov header_sz = sizeof(header_buf); 6289e982dfdSDmitri Tikhonov header_set_ptr(&xhdr, &hbuf, ":method", 7, "where is my car?", 16); 62902c4e282SDmitri Tikhonov enc_st = lsqpack_enc_encode(&enc, 63002c4e282SDmitri Tikhonov enc_buf, &enc_sz, header_buf, &header_sz, 63160620859SDmitri Tikhonov &xhdr, LQEF_NO_HIST_UPD|LQEF_NO_DYN); 6323ce33568SDmitri Tikhonov nw = lsqpack_enc_end_header(&enc, prefix_buf, sizeof(prefix_buf), &hflags); 63302c4e282SDmitri Tikhonov assert(2 == nw); 63402c4e282SDmitri Tikhonov assert(prefix_buf[0] == 0 && prefix_buf[1] == 0); /* Dynamic table not used */ 6353ce33568SDmitri Tikhonov assert(!(hflags & LSQECH_REF_NEW_ENTRIES)); 63602c4e282SDmitri Tikhonov 63702c4e282SDmitri Tikhonov /* Last check that history was not updated: */ 63802c4e282SDmitri Tikhonov s = lsqpack_enc_start_header(&enc, 4, 0); 63902c4e282SDmitri Tikhonov assert(0 == s); 64002c4e282SDmitri Tikhonov enc_sz = sizeof(enc_buf); 64102c4e282SDmitri Tikhonov header_sz = sizeof(header_buf); 6429e982dfdSDmitri Tikhonov header_set_ptr(&xhdr, &hbuf, ":method", 7, "where is my car?", 16); 64302c4e282SDmitri Tikhonov enc_st = lsqpack_enc_encode(&enc, 64402c4e282SDmitri Tikhonov enc_buf, &enc_sz, header_buf, &header_sz, 64560620859SDmitri Tikhonov &xhdr, 0); 64602c4e282SDmitri Tikhonov assert(enc_sz == 0); 64702c4e282SDmitri Tikhonov assert(LQES_OK == enc_st); 6483ce33568SDmitri Tikhonov nw = lsqpack_enc_end_header(&enc, prefix_buf, sizeof(prefix_buf), &hflags); 64902c4e282SDmitri Tikhonov assert(2 == nw); 65002c4e282SDmitri Tikhonov assert(prefix_buf[0] == 0 && prefix_buf[1] == 0); /* Dynamic table not used */ 6513ce33568SDmitri Tikhonov assert(!(hflags & LSQECH_REF_AT_RISK)); 65202c4e282SDmitri Tikhonov 65302c4e282SDmitri Tikhonov lsqpack_enc_cleanup(&enc); 65402c4e282SDmitri Tikhonov} 65502c4e282SDmitri Tikhonov 65602c4e282SDmitri Tikhonov 65760620859SDmitri Tikhonovstruct hblock_ctx 65860620859SDmitri Tikhonov{ 65960620859SDmitri Tikhonov unsigned n_headers; 66060620859SDmitri Tikhonov int finished; 66160620859SDmitri Tikhonov struct lsxpack_header xhdr; 66260620859SDmitri Tikhonov char buf[0x10000]; 66360620859SDmitri Tikhonov}; 66460620859SDmitri Tikhonov 66560620859SDmitri Tikhonov 66660620859SDmitri Tikhonovstatic void 66760620859SDmitri Tikhonovunblocked (void *hblock_ctx_p) 66860620859SDmitri Tikhonov{ 66960620859SDmitri Tikhonov assert(0); /* Not expecting this to be called */ 67060620859SDmitri Tikhonov} 67160620859SDmitri Tikhonov 67260620859SDmitri Tikhonov 67360620859SDmitri Tikhonovstatic struct lsxpack_header * 67460620859SDmitri Tikhonovprepare_decode (void *hblock_ctx_p, struct lsxpack_header *xhdr, size_t space) 67560620859SDmitri Tikhonov{ 67660620859SDmitri Tikhonov struct hblock_ctx *const hctx = hblock_ctx_p; 67760620859SDmitri Tikhonov 67860620859SDmitri Tikhonov if (space > LSXPACK_MAX_STRLEN) 67960620859SDmitri Tikhonov return NULL; 68060620859SDmitri Tikhonov 68160620859SDmitri Tikhonov if (xhdr) 68260620859SDmitri Tikhonov return NULL; 68360620859SDmitri Tikhonov 68460620859SDmitri Tikhonov lsxpack_header_prepare_decode(&hctx->xhdr, hctx->buf, 0, sizeof(hctx->buf)); 68560620859SDmitri Tikhonov return &hctx->xhdr; 68660620859SDmitri Tikhonov} 68760620859SDmitri Tikhonov 68860620859SDmitri Tikhonov 68960620859SDmitri Tikhonovstatic int 69060620859SDmitri Tikhonovprocess_header (void *hblock_ctx_p, struct lsxpack_header *xhdr) 69160620859SDmitri Tikhonov{ 69260620859SDmitri Tikhonov struct hblock_ctx *const hctx = hblock_ctx_p; 69360620859SDmitri Tikhonov 69460620859SDmitri Tikhonov if (xhdr) 69560620859SDmitri Tikhonov ++hctx->n_headers; 69660620859SDmitri Tikhonov else 69760620859SDmitri Tikhonov hctx->finished = 1; 69860620859SDmitri Tikhonov return 0; 69960620859SDmitri Tikhonov} 70060620859SDmitri Tikhonov 70160620859SDmitri Tikhonov 70260620859SDmitri Tikhonovstatic const struct lsqpack_dec_hset_if hset_if = { 70360620859SDmitri Tikhonov .dhi_unblocked = unblocked, 70460620859SDmitri Tikhonov .dhi_prepare_decode = prepare_decode, 70560620859SDmitri Tikhonov .dhi_process_header = process_header, 70660620859SDmitri Tikhonov}; 70760620859SDmitri Tikhonov 70860620859SDmitri Tikhonov 70981059658SDmitri Tikhonovstatic void 71081059658SDmitri Tikhonovtest_discard_header (int err) 71181059658SDmitri Tikhonov{ 71281059658SDmitri Tikhonov struct lsqpack_dec dec; 71381059658SDmitri Tikhonov enum lsqpack_read_header_status rhs; 71481059658SDmitri Tikhonov const unsigned char *buf; 71581059658SDmitri Tikhonov unsigned char header_block[] = "\x00\x00\xC0\x80"; 71660620859SDmitri Tikhonov struct hblock_ctx hctx = { .n_headers = 0, }; 71781059658SDmitri Tikhonov 71860620859SDmitri Tikhonov lsqpack_dec_init(&dec, NULL, 0, 0, &hset_if, LSQPACK_DEC_OPT_HTTP1X); 71981059658SDmitri Tikhonov 72081059658SDmitri Tikhonov buf = header_block; 72160620859SDmitri Tikhonov rhs = lsqpack_dec_header_in(&dec, &hctx, 0, 10, 72260620859SDmitri Tikhonov &buf, 3 + !!err, NULL, NULL); 72381059658SDmitri Tikhonov if (err) 72481059658SDmitri Tikhonov { 72560620859SDmitri Tikhonov assert(hctx.n_headers == 1); 72660620859SDmitri Tikhonov assert(hctx.finished == 0); 72781059658SDmitri Tikhonov assert(LQRHS_ERROR == rhs); 72881059658SDmitri Tikhonov } 72981059658SDmitri Tikhonov else 73081059658SDmitri Tikhonov { 73160620859SDmitri Tikhonov assert(hctx.n_headers == 1); 73260620859SDmitri Tikhonov assert(hctx.finished == 0); 73381059658SDmitri Tikhonov assert(3 == buf - header_block); 73481059658SDmitri Tikhonov assert(LQRHS_NEED == rhs); 73581059658SDmitri Tikhonov lsqpack_dec_cleanup(&dec); 73681059658SDmitri Tikhonov } 73781059658SDmitri Tikhonov} 73881059658SDmitri Tikhonov 73981059658SDmitri Tikhonov 740d6183c77SDmitri Tikhonovstatic void 741d6183c77SDmitri Tikhonovtest_static_bounds_header_block (void) 742d6183c77SDmitri Tikhonov{ 743d6183c77SDmitri Tikhonov struct lsqpack_dec dec; 744d6183c77SDmitri Tikhonov enum lsqpack_read_header_status rhs; 745d6183c77SDmitri Tikhonov const unsigned char *buf; 746d6183c77SDmitri Tikhonov /* Static table index 1000 */ 747d6183c77SDmitri Tikhonov unsigned char header_block[] = "\x00\x00\xFF\xA9\x07"; 74860620859SDmitri Tikhonov struct hblock_ctx hctx = { .n_headers = 0, }; 749d6183c77SDmitri Tikhonov 75060620859SDmitri Tikhonov lsqpack_dec_init(&dec, stderr, 0, 0, &hset_if, LSQPACK_DEC_OPT_HTTP1X); 751d6183c77SDmitri Tikhonov buf = header_block; 75260620859SDmitri Tikhonov rhs = lsqpack_dec_header_in(&dec, &hctx, 0, 10, 75360620859SDmitri Tikhonov &buf, 5, NULL, NULL); 75460620859SDmitri Tikhonov assert(hctx.n_headers == 0); 755d6183c77SDmitri Tikhonov assert(LQRHS_ERROR == rhs); 756d6183c77SDmitri Tikhonov lsqpack_dec_cleanup(&dec); 757d6183c77SDmitri Tikhonov} 758d6183c77SDmitri Tikhonov 759d6183c77SDmitri Tikhonov 760d6183c77SDmitri Tikhonovstatic void 761d6183c77SDmitri Tikhonovtest_static_bounds_enc_stream (void) 762d6183c77SDmitri Tikhonov{ 763d6183c77SDmitri Tikhonov struct lsqpack_dec dec; 764d6183c77SDmitri Tikhonov int r; 765d6183c77SDmitri Tikhonov /* Static table index 1000 */ 766d6183c77SDmitri Tikhonov unsigned char enc_stream[] = "\xFF\xA9\x07\x04" "dude"; 767d6183c77SDmitri Tikhonov 76860620859SDmitri Tikhonov lsqpack_dec_init(&dec, NULL, 0, 0, &hset_if, LSQPACK_DEC_OPT_HTTP1X); 769d6183c77SDmitri Tikhonov r = lsqpack_dec_enc_in(&dec, enc_stream, 8); 770d6183c77SDmitri Tikhonov assert(r == -1); 771d6183c77SDmitri Tikhonov lsqpack_dec_cleanup(&dec); 772d6183c77SDmitri Tikhonov} 773d6183c77SDmitri Tikhonov 774d6183c77SDmitri Tikhonov 77573b010d6SDmitri Tikhonovstatic void 77673b010d6SDmitri Tikhonovtest_wonr_name_too_large_huffman (void) 77773b010d6SDmitri Tikhonov{ 77873b010d6SDmitri Tikhonov struct lsqpack_dec dec; 77973b010d6SDmitri Tikhonov int r; 78073b010d6SDmitri Tikhonov /* Partial Insert Without Name Reference with Huffman-encoded name 78173b010d6SDmitri Tikhonov * string that is larger than 4 x capacity (0x4001) 78273b010d6SDmitri Tikhonov */ 78373b010d6SDmitri Tikhonov unsigned char enc_stream[] = "\x7F\xE2\x7F"; 78473b010d6SDmitri Tikhonov 78560620859SDmitri Tikhonov lsqpack_dec_init(&dec, stderr, 0x1000, 0, &hset_if, LSQPACK_DEC_OPT_HTTP1X); 78673b010d6SDmitri Tikhonov r = lsqpack_dec_enc_in(&dec, enc_stream, 3); 78773b010d6SDmitri Tikhonov assert(r == -1); 78873b010d6SDmitri Tikhonov lsqpack_dec_cleanup(&dec); 78973b010d6SDmitri Tikhonov} 79073b010d6SDmitri Tikhonov 79173b010d6SDmitri Tikhonov 79273b010d6SDmitri Tikhonovstatic void 79373b010d6SDmitri Tikhonovtest_wonr_name_too_large_plain (void) 79473b010d6SDmitri Tikhonov{ 79573b010d6SDmitri Tikhonov struct lsqpack_dec dec; 79673b010d6SDmitri Tikhonov int r; 79773b010d6SDmitri Tikhonov /* Partial Insert Without Name Reference with plain-encoded name 79873b010d6SDmitri Tikhonov * string that is larger than capacity (0x1001) 79973b010d6SDmitri Tikhonov */ 80073b010d6SDmitri Tikhonov unsigned char enc_stream[] = "\x5F\xE2\x1F"; 80173b010d6SDmitri Tikhonov 80260620859SDmitri Tikhonov lsqpack_dec_init(&dec, stderr, 0, 0, &hset_if, LSQPACK_DEC_OPT_HTTP1X); 80373b010d6SDmitri Tikhonov r = lsqpack_dec_enc_in(&dec, enc_stream, 3); 80473b010d6SDmitri Tikhonov assert(r == -1); 80573b010d6SDmitri Tikhonov lsqpack_dec_cleanup(&dec); 80673b010d6SDmitri Tikhonov} 80773b010d6SDmitri Tikhonov 80873b010d6SDmitri Tikhonov 80973b010d6SDmitri Tikhonovstatic void 81073b010d6SDmitri Tikhonovtest_wonr_value_too_large_huffman (void) 81173b010d6SDmitri Tikhonov{ 81273b010d6SDmitri Tikhonov struct lsqpack_dec dec; 81373b010d6SDmitri Tikhonov int r; 81473b010d6SDmitri Tikhonov /* Partial Insert Without Name Reference with Huffman-encoded value 81573b010d6SDmitri Tikhonov * string that, together with name, is larger than 4 x capacity (0x3FFF) 81673b010d6SDmitri Tikhonov */ 81773b010d6SDmitri Tikhonov unsigned char enc_stream[] = "\x42OK\xFF\x80\x7F"; 81873b010d6SDmitri Tikhonov 81960620859SDmitri Tikhonov lsqpack_dec_init(&dec, stderr, 0, 0, &hset_if, LSQPACK_DEC_OPT_HTTP1X); 82073b010d6SDmitri Tikhonov r = lsqpack_dec_enc_in(&dec, enc_stream, 6); 82173b010d6SDmitri Tikhonov assert(r == -1); 82273b010d6SDmitri Tikhonov lsqpack_dec_cleanup(&dec); 82373b010d6SDmitri Tikhonov} 82473b010d6SDmitri Tikhonov 82573b010d6SDmitri Tikhonov 82673b010d6SDmitri Tikhonovstatic void 82773b010d6SDmitri Tikhonovtest_wonr_value_too_large_plain (void) 82873b010d6SDmitri Tikhonov{ 82973b010d6SDmitri Tikhonov struct lsqpack_dec dec; 83073b010d6SDmitri Tikhonov int r; 83173b010d6SDmitri Tikhonov /* Partial Insert Without Name Reference with plain-encoded value 83273b010d6SDmitri Tikhonov * string that, together with name, is larger than capacity (0xFFF) 83373b010d6SDmitri Tikhonov */ 83473b010d6SDmitri Tikhonov unsigned char enc_stream[] = "\x42OK\x7F\x80\x1F"; 83573b010d6SDmitri Tikhonov 83660620859SDmitri Tikhonov lsqpack_dec_init(&dec, stderr, 0x1000, 0, &hset_if, LSQPACK_DEC_OPT_HTTP1X); 83773b010d6SDmitri Tikhonov r = lsqpack_dec_enc_in(&dec, enc_stream, 6); 83873b010d6SDmitri Tikhonov assert(r == -1); 83973b010d6SDmitri Tikhonov lsqpack_dec_cleanup(&dec); 84073b010d6SDmitri Tikhonov} 84173b010d6SDmitri Tikhonov 84273b010d6SDmitri Tikhonov 84373b010d6SDmitri Tikhonovstatic void 84473b010d6SDmitri Tikhonovtest_winr_value_too_large_huffman (void) 84573b010d6SDmitri Tikhonov{ 84673b010d6SDmitri Tikhonov struct lsqpack_dec dec; 84773b010d6SDmitri Tikhonov int r; 84873b010d6SDmitri Tikhonov /* Partial Insert With Name Reference with Huffman-encoded value 84973b010d6SDmitri Tikhonov * string that, together with name, is larger than 4 x capacity (0x3FE4) 85073b010d6SDmitri Tikhonov */ 85173b010d6SDmitri Tikhonov /* Refer to static entry 79: access-control-refer-headers (length 28) */ 85273b010d6SDmitri Tikhonov unsigned char enc_stream[] = "\xFF\x10\xFF\xE5\x7E"; 85373b010d6SDmitri Tikhonov 85460620859SDmitri Tikhonov lsqpack_dec_init(&dec, stderr, 0x1000, 0, &hset_if, LSQPACK_DEC_OPT_HTTP1X); 85573b010d6SDmitri Tikhonov r = lsqpack_dec_enc_in(&dec, enc_stream, 5); 85673b010d6SDmitri Tikhonov assert(r == -1); 85773b010d6SDmitri Tikhonov lsqpack_dec_cleanup(&dec); 85873b010d6SDmitri Tikhonov} 85973b010d6SDmitri Tikhonov 86073b010d6SDmitri Tikhonov 86173b010d6SDmitri Tikhonovstatic void 86273b010d6SDmitri Tikhonovtest_winr_value_too_large_plain (void) 86373b010d6SDmitri Tikhonov{ 86473b010d6SDmitri Tikhonov struct lsqpack_dec dec; 86573b010d6SDmitri Tikhonov int r; 86673b010d6SDmitri Tikhonov /* Partial Insert With Name Reference with plain-encoded value 86773b010d6SDmitri Tikhonov * string that, together with name, is larger than capacity (0xFE4) 86873b010d6SDmitri Tikhonov */ 86973b010d6SDmitri Tikhonov /* Refer to static entry 79: access-control-refer-headers (length 28) */ 87073b010d6SDmitri Tikhonov unsigned char enc_stream[] = "\xFF\x10\x7F\xE5\x1E"; 87173b010d6SDmitri Tikhonov 87260620859SDmitri Tikhonov lsqpack_dec_init(&dec, stderr, 0x1000, 0, &hset_if, LSQPACK_DEC_OPT_HTTP1X); 87373b010d6SDmitri Tikhonov r = lsqpack_dec_enc_in(&dec, enc_stream, 5); 87473b010d6SDmitri Tikhonov assert(r == -1); 87573b010d6SDmitri Tikhonov lsqpack_dec_cleanup(&dec); 87673b010d6SDmitri Tikhonov} 87773b010d6SDmitri Tikhonov 87873b010d6SDmitri Tikhonov 87941eedfafSDmitri Tikhonov/* This is an odd case, but if the first call should provide no input at all, 88041eedfafSDmitri Tikhonov * the decoder should return LQRHS_NEED 88141eedfafSDmitri Tikhonov */ 88241eedfafSDmitri Tikhonovstatic void 88341eedfafSDmitri Tikhonovtest_dec_header_zero_in (void) 88441eedfafSDmitri Tikhonov{ 88541eedfafSDmitri Tikhonov struct lsqpack_dec dec; 88641eedfafSDmitri Tikhonov struct lsqpack_header_list *hlist; 88741eedfafSDmitri Tikhonov enum lsqpack_read_header_status rhs; 888daec9888SLiteSpeed Tech const unsigned char *buf = (unsigned char *) ""; 88960620859SDmitri Tikhonov struct hblock_ctx hctx = { .n_headers = 0, }; 89041eedfafSDmitri Tikhonov 89160620859SDmitri Tikhonov lsqpack_dec_init(&dec, stderr, 0x1000, 0, &hset_if, LSQPACK_DEC_OPT_HTTP1X); 89241eedfafSDmitri Tikhonov 89341eedfafSDmitri Tikhonov rhs = lsqpack_dec_header_in(&dec, 89460620859SDmitri Tikhonov &hctx /* hblock */, 89541eedfafSDmitri Tikhonov 2 /* Stream ID */, 89641eedfafSDmitri Tikhonov 100 /* How long the thing is */, 89741eedfafSDmitri Tikhonov &buf, 89841eedfafSDmitri Tikhonov 0 /* How many bytes are available */, 89941eedfafSDmitri Tikhonov NULL, 0); 90041eedfafSDmitri Tikhonov assert(LQRHS_NEED == rhs); 90141eedfafSDmitri Tikhonov 90241eedfafSDmitri Tikhonov lsqpack_dec_cleanup(&dec); 90341eedfafSDmitri Tikhonov} 90441eedfafSDmitri Tikhonov 90541eedfafSDmitri Tikhonov 9068a627c4bSDmitri Tikhonov/* Header that's too should should return LQRHS_ERROR */ 9078a627c4bSDmitri Tikhonovstatic void 9088a627c4bSDmitri Tikhonovtest_dec_header_too_short (size_t header_size) 9098a627c4bSDmitri Tikhonov{ 9108a627c4bSDmitri Tikhonov struct lsqpack_dec dec; 9118a627c4bSDmitri Tikhonov struct lsqpack_header_list *hlist; 9128a627c4bSDmitri Tikhonov enum lsqpack_read_header_status rhs; 913daec9888SLiteSpeed Tech const unsigned char *buf = (unsigned char *) ""; 91460620859SDmitri Tikhonov struct hblock_ctx hctx = { .n_headers = 0, }; 9158a627c4bSDmitri Tikhonov 91660620859SDmitri Tikhonov lsqpack_dec_init(&dec, stderr, 0x1000, 0, &hset_if, LSQPACK_DEC_OPT_HTTP1X); 9178a627c4bSDmitri Tikhonov 9188a627c4bSDmitri Tikhonov rhs = lsqpack_dec_header_in(&dec, 91960620859SDmitri Tikhonov &hctx /* hblock */, 9208a627c4bSDmitri Tikhonov 2 /* Stream ID */, 9218a627c4bSDmitri Tikhonov header_size, 9228a627c4bSDmitri Tikhonov &buf, 9238a627c4bSDmitri Tikhonov 0 /* How many bytes are available */, 9248a627c4bSDmitri Tikhonov NULL, 0); 9258a627c4bSDmitri Tikhonov assert(LQRHS_ERROR == rhs); 9268a627c4bSDmitri Tikhonov 9278a627c4bSDmitri Tikhonov lsqpack_dec_cleanup(&dec); 9288a627c4bSDmitri Tikhonov} 9298a627c4bSDmitri Tikhonov 9308a627c4bSDmitri Tikhonov 931147b1758SDmitri Tikhonovstatic void 932147b1758SDmitri Tikhonovtest_enc_risked_streams_test (const char *test) 933147b1758SDmitri Tikhonov{ 934147b1758SDmitri Tikhonov struct lsqpack_enc enc; 935147b1758SDmitri Tikhonov int s; 936147b1758SDmitri Tikhonov size_t sz; 937147b1758SDmitri Tikhonov ssize_t ssz; 938147b1758SDmitri Tikhonov long arg; 939147b1758SDmitri Tikhonov enum lsqpack_enc_status es; 940147b1758SDmitri Tikhonov unsigned n_seqnos = 0; 941147b1758SDmitri Tikhonov struct { 942147b1758SDmitri Tikhonov uint64_t stream_id; 943147b1758SDmitri Tikhonov unsigned seqno; 944147b1758SDmitri Tikhonov } seqnos[10], *seq_el; 945147b1758SDmitri Tikhonov unsigned char buf[0x100]; 946147b1758SDmitri Tikhonov unsigned char *end_cmd; 947147b1758SDmitri Tikhonov int expect_failure; 94860620859SDmitri Tikhonov struct lsxpack_header xhdr; 9499e982dfdSDmitri Tikhonov struct header_buf hbuf; 950147b1758SDmitri Tikhonov 951147b1758SDmitri Tikhonov const struct { 952147b1758SDmitri Tikhonov const char *name; 953147b1758SDmitri Tikhonov unsigned name_len; 954147b1758SDmitri Tikhonov const char *value; 955147b1758SDmitri Tikhonov unsigned value_len; 956147b1758SDmitri Tikhonov } headers[] = { 957147b1758SDmitri Tikhonov { "some", 4, "header", 6, }, 958147b1758SDmitri Tikhonov { "another", 7, "header", 6, }, 959147b1758SDmitri Tikhonov { "and yet another", 15, "header, duh", 11, }, 960147b1758SDmitri Tikhonov }; 961147b1758SDmitri Tikhonov 962147b1758SDmitri Tikhonov fprintf(stderr, "BEGIN TEST %s\n", test); 963147b1758SDmitri Tikhonov lsqpack_enc_preinit(&enc, stderr); 9649e982dfdSDmitri Tikhonov hbuf.off = 0; 965147b1758SDmitri Tikhonov 966147b1758SDmitri Tikhonov while (1) 967147b1758SDmitri Tikhonov { 968147b1758SDmitri Tikhonov expect_failure = isupper(*test); 969147b1758SDmitri Tikhonov switch (*test++) 970147b1758SDmitri Tikhonov { 971147b1758SDmitri Tikhonov case 'i': 972147b1758SDmitri Tikhonov arg = strtol(test, (char**)&test, 10); 973147b1758SDmitri Tikhonov sz = sizeof(buf); 974147b1758SDmitri Tikhonov s = lsqpack_enc_init(&enc, stderr, 0x1000, 0x1000, 975147b1758SDmitri Tikhonov (unsigned) arg, 0, buf, &sz); 976147b1758SDmitri Tikhonov assert(s == 0); 977147b1758SDmitri Tikhonov break; 978147b1758SDmitri Tikhonov case 'r': 979147b1758SDmitri Tikhonov arg = strtol(test, (char**)&test, 10); 980147b1758SDmitri Tikhonov assert((unsigned) arg == enc.qpe_cur_streams_at_risk); 981147b1758SDmitri Tikhonov break; 982147b1758SDmitri Tikhonov case 's': /* Start header */ 983147b1758SDmitri Tikhonov arg = strtol(test, (char**)&test, 10); 984147b1758SDmitri Tikhonov for (seq_el = seqnos; seq_el < seqnos + n_seqnos; ++seq_el) 985147b1758SDmitri Tikhonov if (seq_el->stream_id == arg) 986147b1758SDmitri Tikhonov break; 987147b1758SDmitri Tikhonov assert(seq_el < seqnos + sizeof(seqnos) / sizeof(seqnos[0])); 988147b1758SDmitri Tikhonov if (seq_el == seqnos + n_seqnos) 989147b1758SDmitri Tikhonov { 990147b1758SDmitri Tikhonov ++n_seqnos; 991147b1758SDmitri Tikhonov seq_el->stream_id = arg; 992147b1758SDmitri Tikhonov seq_el->seqno = 0; 993147b1758SDmitri Tikhonov } 994147b1758SDmitri Tikhonov s = lsqpack_enc_start_header(&enc, arg, seq_el->seqno++); 995147b1758SDmitri Tikhonov assert(s == 0); 996147b1758SDmitri Tikhonov break; 997147b1758SDmitri Tikhonov case 'c': /* En*C*ode */ 998147b1758SDmitri Tikhonov arg = strtol(test, (char**)&test, 10); 999147b1758SDmitri Tikhonov sz = sizeof(buf); 1000147b1758SDmitri Tikhonov /* We ignore the output */ 10019e982dfdSDmitri Tikhonov header_set_ptr(&xhdr, &hbuf, 1002147b1758SDmitri Tikhonov headers[arg].name, headers[arg].name_len, 100360620859SDmitri Tikhonov headers[arg].value, headers[arg].value_len); 100460620859SDmitri Tikhonov es = lsqpack_enc_encode(&enc, buf, &sz, buf, &sz, &xhdr, 0); 1005147b1758SDmitri Tikhonov assert(LQES_OK == es); 1006147b1758SDmitri Tikhonov break; 1007147b1758SDmitri Tikhonov case 'e': /* End header */ 1008147b1758SDmitri Tikhonov ssz = lsqpack_enc_end_header(&enc, buf, sizeof(buf), NULL); 1009147b1758SDmitri Tikhonov assert(ssz > 0); 1010147b1758SDmitri Tikhonov break; 1011147b1758SDmitri Tikhonov case 'a': /* ACK header */ 1012147b1758SDmitri Tikhonov case 'A': 1013147b1758SDmitri Tikhonov arg = strtol(test, (char**)&test, 10); 1014147b1758SDmitri Tikhonov buf[0] = 0x80; 1015147b1758SDmitri Tikhonov end_cmd = lsqpack_enc_int(buf, buf + sizeof(buf), arg, 7); 1016147b1758SDmitri Tikhonov s = lsqpack_enc_decoder_in(&enc, buf, end_cmd - buf); 1017147b1758SDmitri Tikhonov if (expect_failure) 1018147b1758SDmitri Tikhonov assert(s < 0); 1019147b1758SDmitri Tikhonov else 1020147b1758SDmitri Tikhonov assert(s == 0); 1021147b1758SDmitri Tikhonov break; 1022147b1758SDmitri Tikhonov case 'L': /* Cancel header */ 1023147b1758SDmitri Tikhonov case 'l': 1024147b1758SDmitri Tikhonov arg = strtol(test, (char**)&test, 10); 1025147b1758SDmitri Tikhonov buf[0] = 0x40; 1026147b1758SDmitri Tikhonov end_cmd = lsqpack_enc_int(buf, buf + sizeof(buf), arg, 6); 1027147b1758SDmitri Tikhonov s = lsqpack_enc_decoder_in(&enc, buf, end_cmd - buf); 1028147b1758SDmitri Tikhonov if (expect_failure) 1029147b1758SDmitri Tikhonov assert(s < 0); 1030147b1758SDmitri Tikhonov else 1031147b1758SDmitri Tikhonov assert(s == 0); 1032147b1758SDmitri Tikhonov break; 1033147b1758SDmitri Tikhonov case 'N': /* Insert Count Increment */ 1034147b1758SDmitri Tikhonov case 'n': 1035147b1758SDmitri Tikhonov arg = strtol(test, (char**)&test, 10); 1036147b1758SDmitri Tikhonov buf[0] = 0x00; 1037147b1758SDmitri Tikhonov end_cmd = lsqpack_enc_int(buf, buf + sizeof(buf), arg, 6); 1038147b1758SDmitri Tikhonov s = lsqpack_enc_decoder_in(&enc, buf, end_cmd - buf); 1039147b1758SDmitri Tikhonov if (expect_failure) 1040147b1758SDmitri Tikhonov assert(s < 0); 1041147b1758SDmitri Tikhonov else 1042147b1758SDmitri Tikhonov assert(s == 0); 1043147b1758SDmitri Tikhonov break; 1044147b1758SDmitri Tikhonov break; 1045147b1758SDmitri Tikhonov case '\0': 1046147b1758SDmitri Tikhonov goto end; 1047147b1758SDmitri Tikhonov default: 1048147b1758SDmitri Tikhonov assert("unknown action"); 1049147b1758SDmitri Tikhonov goto end; 1050147b1758SDmitri Tikhonov } 1051147b1758SDmitri Tikhonov } 1052147b1758SDmitri Tikhonov 1053147b1758SDmitri Tikhonov end: 1054147b1758SDmitri Tikhonov lsqpack_enc_cleanup(&enc); 1055147b1758SDmitri Tikhonov} 1056147b1758SDmitri Tikhonov 1057147b1758SDmitri Tikhonov 1058147b1758SDmitri Tikhonovstatic void 1059147b1758SDmitri Tikhonovtest_enc_risked_streams (void) 1060147b1758SDmitri Tikhonov{ 1061147b1758SDmitri Tikhonov const char **test; 1062147b1758SDmitri Tikhonov const char *tests[] = 1063147b1758SDmitri Tikhonov { 1064147b1758SDmitri Tikhonov "i0r0s1c0er0", 1065147b1758SDmitri Tikhonov "i1r0s1c0er0s2c0er1A1r1a2r0", 1066147b1758SDmitri Tikhonov "i1r0s1c0er0s2c0er1s2c0c1er1a2r0a2r0", 1067147b1758SDmitri Tikhonov 1068147b1758SDmitri Tikhonov "i1r0s1c0c1er0" 1069147b1758SDmitri Tikhonov "s2c0er1" 1070147b1758SDmitri Tikhonov "s2c0c1er1" 1071147b1758SDmitri Tikhonov "a2r1" /* Ack first seqno, # of risked streams still 1 */ 1072147b1758SDmitri Tikhonov "a2r0", 1073147b1758SDmitri Tikhonov 1074147b1758SDmitri Tikhonov "i1r0s1c0c1er0" 1075147b1758SDmitri Tikhonov "s2c0er1" 1076147b1758SDmitri Tikhonov "s2c0c1er1" 1077147b1758SDmitri Tikhonov "l2r0" /* Cancel */ 1078147b1758SDmitri Tikhonov , 1079147b1758SDmitri Tikhonov 1080147b1758SDmitri Tikhonov "i1r0s1c0c1er0" 1081147b1758SDmitri Tikhonov "s2c0er1" 1082147b1758SDmitri Tikhonov "s2c0c1er1" 1083147b1758SDmitri Tikhonov "N3" 1084147b1758SDmitri Tikhonov "n1r1" 1085147b1758SDmitri Tikhonov "n1r0" 1086147b1758SDmitri Tikhonov , 1087147b1758SDmitri Tikhonov 1088147b1758SDmitri Tikhonov NULL, 1089147b1758SDmitri Tikhonov }; 1090147b1758SDmitri Tikhonov 1091147b1758SDmitri Tikhonov for (test = tests; *test; ++test) 1092147b1758SDmitri Tikhonov test_enc_risked_streams_test(*test); 1093147b1758SDmitri Tikhonov} 1094147b1758SDmitri Tikhonov 1095147b1758SDmitri Tikhonov 109643a63c18SDmitri Tikhonovint 109743a63c18SDmitri Tikhonovmain (void) 109843a63c18SDmitri Tikhonov{ 109943a63c18SDmitri Tikhonov unsigned i; 110043a63c18SDmitri Tikhonov 110143a63c18SDmitri Tikhonov for (i = 0; i < sizeof(header_block_tests) 110243a63c18SDmitri Tikhonov / sizeof(header_block_tests[0]); ++i) 110318555864SDmitri Tikhonov { 110443a63c18SDmitri Tikhonov run_header_test(&header_block_tests[i]); 110518555864SDmitri Tikhonov run_decoded_headers_test(&header_block_tests[i]); 110618555864SDmitri Tikhonov } 110743a63c18SDmitri Tikhonov 1108d4822b2bSDaan De Meyer run_header_cancellation_test(&header_block_tests[0]); 1109b43d0c9bSDmitri Tikhonov test_enc_init(); 111002c4e282SDmitri Tikhonov test_push_promise(); 111181059658SDmitri Tikhonov test_discard_header(0); 111281059658SDmitri Tikhonov test_discard_header(1); 1113d6183c77SDmitri Tikhonov test_static_bounds_header_block(); 1114d6183c77SDmitri Tikhonov test_static_bounds_enc_stream(); 111573b010d6SDmitri Tikhonov test_wonr_name_too_large_huffman(); 111673b010d6SDmitri Tikhonov test_wonr_name_too_large_plain(); 111773b010d6SDmitri Tikhonov test_wonr_value_too_large_huffman(); 111873b010d6SDmitri Tikhonov test_wonr_value_too_large_plain(); 111973b010d6SDmitri Tikhonov test_winr_value_too_large_huffman(); 112073b010d6SDmitri Tikhonov test_winr_value_too_large_plain(); 112141eedfafSDmitri Tikhonov test_dec_header_zero_in(); 11228a627c4bSDmitri Tikhonov test_dec_header_too_short(0); 11238a627c4bSDmitri Tikhonov test_dec_header_too_short(1); 1124147b1758SDmitri Tikhonov test_enc_risked_streams(); 1125d4822b2bSDaan De Meyer 112643a63c18SDmitri Tikhonov return 0; 112743a63c18SDmitri Tikhonov} 1128