1/*
2 * nghttp2 - HTTP/2 C Library
3 *
4 * Copyright (c) 2013 Tatsuhiro Tsujikawa
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25#include "nghttp2_hd_test.h"
26
27#include <stdio.h>
28#include <assert.h>
29
30#include <CUnit/CUnit.h>
31
32#include "nghttp2_hd.h"
33#include "nghttp2_frame.h"
34#include "nghttp2_test_helper.h"
35
36void test_nghttp2_hd_deflate(void) {
37  nghttp2_hd_deflater deflater;
38  nghttp2_hd_inflater inflater;
39  nghttp2_nv nva1[] = {MAKE_NV(":path", "/my-example/index.html"),
40                       MAKE_NV(":scheme", "https"), MAKE_NV("hello", "world")};
41  nghttp2_nv nva2[] = {MAKE_NV(":path", "/script.js"),
42                       MAKE_NV(":scheme", "https")};
43  nghttp2_nv nva3[] = {MAKE_NV("cookie", "k1=v1"), MAKE_NV("cookie", "k2=v2"),
44                       MAKE_NV("via", "proxy")};
45  nghttp2_nv nva4[] = {MAKE_NV(":path", "/style.css"),
46                       MAKE_NV("cookie", "k1=v1"), MAKE_NV("cookie", "k1=v1")};
47  nghttp2_nv nva5[] = {MAKE_NV(":path", "/style.css"),
48                       MAKE_NV("x-nghttp2", "")};
49  nghttp2_bufs bufs;
50  ssize_t blocklen;
51  nva_out out;
52  int rv;
53  nghttp2_mem *mem;
54
55  mem = nghttp2_mem_default();
56  frame_pack_bufs_init(&bufs);
57
58  nva_out_init(&out);
59  CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater, mem));
60  CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater, mem));
61
62  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva1, ARRLEN(nva1));
63  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
64
65  CU_ASSERT(0 == rv);
66  CU_ASSERT(blocklen > 0);
67  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
68
69  CU_ASSERT(3 == out.nvlen);
70  assert_nv_equal(nva1, out.nva, 3, mem);
71
72  nva_out_reset(&out, mem);
73  nghttp2_bufs_reset(&bufs);
74
75  /* Second headers */
76  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, ARRLEN(nva2));
77  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
78
79  CU_ASSERT(0 == rv);
80  CU_ASSERT(blocklen > 0);
81  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
82
83  CU_ASSERT(2 == out.nvlen);
84  assert_nv_equal(nva2, out.nva, 2, mem);
85
86  nva_out_reset(&out, mem);
87  nghttp2_bufs_reset(&bufs);
88
89  /* Third headers, including same header field name, but value is not
90     the same. */
91  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva3, ARRLEN(nva3));
92  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
93
94  CU_ASSERT(0 == rv);
95  CU_ASSERT(blocklen > 0);
96  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
97
98  CU_ASSERT(3 == out.nvlen);
99  assert_nv_equal(nva3, out.nva, 3, mem);
100
101  nva_out_reset(&out, mem);
102  nghttp2_bufs_reset(&bufs);
103
104  /* Fourth headers, including duplicate header fields. */
105  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva4, ARRLEN(nva4));
106  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
107
108  CU_ASSERT(0 == rv);
109  CU_ASSERT(blocklen > 0);
110  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
111
112  CU_ASSERT(3 == out.nvlen);
113  assert_nv_equal(nva4, out.nva, 3, mem);
114
115  nva_out_reset(&out, mem);
116  nghttp2_bufs_reset(&bufs);
117
118  /* Fifth headers includes empty value */
119  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva5, ARRLEN(nva5));
120  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
121
122  CU_ASSERT(0 == rv);
123  CU_ASSERT(blocklen > 0);
124  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
125
126  CU_ASSERT(2 == out.nvlen);
127  assert_nv_equal(nva5, out.nva, 2, mem);
128
129  nva_out_reset(&out, mem);
130  nghttp2_bufs_reset(&bufs);
131
132  /* Cleanup */
133  nghttp2_bufs_free(&bufs);
134  nghttp2_hd_inflate_free(&inflater);
135  nghttp2_hd_deflate_free(&deflater);
136}
137
138void test_nghttp2_hd_deflate_same_indexed_repr(void) {
139  nghttp2_hd_deflater deflater;
140  nghttp2_hd_inflater inflater;
141  nghttp2_nv nva1[] = {MAKE_NV("host", "alpha"), MAKE_NV("host", "alpha")};
142  nghttp2_nv nva2[] = {MAKE_NV("host", "alpha"), MAKE_NV("host", "alpha"),
143                       MAKE_NV("host", "alpha")};
144  nghttp2_bufs bufs;
145  ssize_t blocklen;
146  nva_out out;
147  int rv;
148  nghttp2_mem *mem;
149
150  mem = nghttp2_mem_default();
151  frame_pack_bufs_init(&bufs);
152
153  nva_out_init(&out);
154  CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater, mem));
155  CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater, mem));
156
157  /* Encode 2 same headers.  Emit 1 literal reprs and 1 index repr. */
158  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva1, ARRLEN(nva1));
159  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
160
161  CU_ASSERT(0 == rv);
162  CU_ASSERT(blocklen > 0);
163  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
164
165  CU_ASSERT(2 == out.nvlen);
166  assert_nv_equal(nva1, out.nva, 2, mem);
167
168  nva_out_reset(&out, mem);
169  nghttp2_bufs_reset(&bufs);
170
171  /* Encode 3 same headers.  This time, emits 3 index reprs. */
172  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, ARRLEN(nva2));
173  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
174
175  CU_ASSERT(0 == rv);
176  CU_ASSERT(blocklen == 3);
177  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
178
179  CU_ASSERT(3 == out.nvlen);
180  assert_nv_equal(nva2, out.nva, 3, mem);
181
182  nva_out_reset(&out, mem);
183  nghttp2_bufs_reset(&bufs);
184
185  /* Cleanup */
186  nghttp2_bufs_free(&bufs);
187  nghttp2_hd_inflate_free(&inflater);
188  nghttp2_hd_deflate_free(&deflater);
189}
190
191void test_nghttp2_hd_inflate_indexed(void) {
192  nghttp2_hd_inflater inflater;
193  nghttp2_bufs bufs;
194  ssize_t blocklen;
195  nghttp2_nv nv = MAKE_NV(":path", "/");
196  nva_out out;
197  nghttp2_mem *mem;
198
199  mem = nghttp2_mem_default();
200  frame_pack_bufs_init(&bufs);
201
202  nva_out_init(&out);
203  nghttp2_hd_inflate_init(&inflater, mem);
204
205  nghttp2_bufs_addb(&bufs, (1 << 7) | 4);
206
207  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
208
209  CU_ASSERT(1 == blocklen);
210  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
211
212  CU_ASSERT(1 == out.nvlen);
213
214  assert_nv_equal(&nv, out.nva, 1, mem);
215
216  nva_out_reset(&out, mem);
217  nghttp2_bufs_reset(&bufs);
218
219  /* index = 0 is error */
220  nghttp2_bufs_addb(&bufs, 1 << 7);
221
222  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
223
224  CU_ASSERT(1 == blocklen);
225  CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
226            inflate_hd(&inflater, &out, &bufs, 0, mem));
227
228  nghttp2_bufs_free(&bufs);
229  nghttp2_hd_inflate_free(&inflater);
230}
231
232void test_nghttp2_hd_inflate_indname_noinc(void) {
233  nghttp2_hd_inflater inflater;
234  nghttp2_bufs bufs;
235  ssize_t blocklen;
236  nghttp2_nv nv[] = {/* Huffman */
237                     MAKE_NV("user-agent", "nghttp2"),
238                     /* Expecting no huffman */
239                     MAKE_NV("user-agent", "x")};
240  size_t i;
241  nva_out out;
242  nghttp2_mem *mem;
243
244  mem = nghttp2_mem_default();
245  frame_pack_bufs_init(&bufs);
246
247  nva_out_init(&out);
248  nghttp2_hd_inflate_init(&inflater, mem);
249
250  for (i = 0; i < ARRLEN(nv); ++i) {
251    CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 57, &nv[i],
252                                                 NGHTTP2_HD_WITHOUT_INDEXING));
253
254    blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
255
256    CU_ASSERT(blocklen > 0);
257    CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
258
259    CU_ASSERT(1 == out.nvlen);
260    assert_nv_equal(&nv[i], out.nva, 1, mem);
261    CU_ASSERT(0 == inflater.ctx.hd_table.len);
262    CU_ASSERT(61 == nghttp2_hd_inflate_get_num_table_entries(&inflater));
263
264    nva_out_reset(&out, mem);
265    nghttp2_bufs_reset(&bufs);
266  }
267
268  nghttp2_bufs_free(&bufs);
269  nghttp2_hd_inflate_free(&inflater);
270}
271
272void test_nghttp2_hd_inflate_indname_inc(void) {
273  nghttp2_hd_inflater inflater;
274  nghttp2_bufs bufs;
275  ssize_t blocklen;
276  nghttp2_nv nv = MAKE_NV("user-agent", "nghttp2");
277  nva_out out;
278  nghttp2_mem *mem;
279
280  mem = nghttp2_mem_default();
281  frame_pack_bufs_init(&bufs);
282
283  nva_out_init(&out);
284  nghttp2_hd_inflate_init(&inflater, mem);
285
286  CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 57, &nv,
287                                               NGHTTP2_HD_WITH_INDEXING));
288
289  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
290
291  CU_ASSERT(blocklen > 0);
292  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
293
294  CU_ASSERT(1 == out.nvlen);
295  assert_nv_equal(&nv, out.nva, 1, mem);
296  CU_ASSERT(1 == inflater.ctx.hd_table.len);
297  CU_ASSERT(62 == nghttp2_hd_inflate_get_num_table_entries(&inflater));
298  assert_nv_equal(
299      &nv,
300      nghttp2_hd_inflate_get_table_entry(
301          &inflater, NGHTTP2_STATIC_TABLE_LENGTH + inflater.ctx.hd_table.len),
302      1, mem);
303
304  nva_out_reset(&out, mem);
305  nghttp2_bufs_free(&bufs);
306  nghttp2_hd_inflate_free(&inflater);
307}
308
309void test_nghttp2_hd_inflate_indname_inc_eviction(void) {
310  nghttp2_hd_inflater inflater;
311  nghttp2_bufs bufs;
312  ssize_t blocklen;
313  uint8_t value[1025];
314  nva_out out;
315  nghttp2_nv nv;
316  nghttp2_mem *mem;
317
318  mem = nghttp2_mem_default();
319  frame_pack_bufs_init(&bufs);
320
321  nva_out_init(&out);
322  nghttp2_hd_inflate_init(&inflater, mem);
323
324  memset(value, '0', sizeof(value));
325  value[sizeof(value) - 1] = '\0';
326  nv.value = value;
327  nv.valuelen = sizeof(value) - 1;
328
329  nv.flags = NGHTTP2_NV_FLAG_NONE;
330
331  CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 14, &nv,
332                                               NGHTTP2_HD_WITH_INDEXING));
333  CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 15, &nv,
334                                               NGHTTP2_HD_WITH_INDEXING));
335  CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 16, &nv,
336                                               NGHTTP2_HD_WITH_INDEXING));
337  CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 17, &nv,
338                                               NGHTTP2_HD_WITH_INDEXING));
339
340  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
341
342  CU_ASSERT(blocklen > 0);
343
344  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
345
346  CU_ASSERT(4 == out.nvlen);
347  CU_ASSERT(14 == out.nva[0].namelen);
348  CU_ASSERT(0 == memcmp("accept-charset", out.nva[0].name, out.nva[0].namelen));
349  CU_ASSERT(sizeof(value) - 1 == out.nva[0].valuelen);
350
351  nva_out_reset(&out, mem);
352  nghttp2_bufs_reset(&bufs);
353
354  CU_ASSERT(3 == inflater.ctx.hd_table.len);
355  CU_ASSERT(64 == nghttp2_hd_inflate_get_num_table_entries(&inflater));
356
357  nghttp2_bufs_free(&bufs);
358  nghttp2_hd_inflate_free(&inflater);
359}
360
361void test_nghttp2_hd_inflate_newname_noinc(void) {
362  nghttp2_hd_inflater inflater;
363  nghttp2_bufs bufs;
364  ssize_t blocklen;
365  nghttp2_nv nv[] = {/* Expecting huffman for both */
366                     MAKE_NV("my-long-content-length", "nghttp2"),
367                     /* Expecting no huffman for both */
368                     MAKE_NV("x", "y"),
369                     /* Huffman for key only */
370                     MAKE_NV("my-long-content-length", "y"),
371                     /* Huffman for value only */
372                     MAKE_NV("x", "nghttp2")};
373  size_t i;
374  nva_out out;
375  nghttp2_mem *mem;
376
377  mem = nghttp2_mem_default();
378  frame_pack_bufs_init(&bufs);
379
380  nva_out_init(&out);
381  nghttp2_hd_inflate_init(&inflater, mem);
382  for (i = 0; i < ARRLEN(nv); ++i) {
383    CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&bufs, &nv[i],
384                                                 NGHTTP2_HD_WITHOUT_INDEXING));
385
386    blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
387
388    CU_ASSERT(blocklen > 0);
389    CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
390
391    CU_ASSERT(1 == out.nvlen);
392    assert_nv_equal(&nv[i], out.nva, 1, mem);
393    CU_ASSERT(0 == inflater.ctx.hd_table.len);
394
395    nva_out_reset(&out, mem);
396    nghttp2_bufs_reset(&bufs);
397  }
398
399  nghttp2_bufs_free(&bufs);
400  nghttp2_hd_inflate_free(&inflater);
401}
402
403void test_nghttp2_hd_inflate_newname_inc(void) {
404  nghttp2_hd_inflater inflater;
405  nghttp2_bufs bufs;
406  ssize_t blocklen;
407  nghttp2_nv nv = MAKE_NV("x-rel", "nghttp2");
408  nva_out out;
409  nghttp2_mem *mem;
410
411  mem = nghttp2_mem_default();
412  frame_pack_bufs_init(&bufs);
413
414  nva_out_init(&out);
415  nghttp2_hd_inflate_init(&inflater, mem);
416
417  CU_ASSERT(
418      0 == nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING));
419
420  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
421
422  CU_ASSERT(blocklen > 0);
423  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
424
425  CU_ASSERT(1 == out.nvlen);
426  assert_nv_equal(&nv, out.nva, 1, mem);
427  CU_ASSERT(1 == inflater.ctx.hd_table.len);
428  assert_nv_equal(
429      &nv,
430      nghttp2_hd_inflate_get_table_entry(
431          &inflater, NGHTTP2_STATIC_TABLE_LENGTH + inflater.ctx.hd_table.len),
432      1, mem);
433
434  nva_out_reset(&out, mem);
435  nghttp2_bufs_free(&bufs);
436  nghttp2_hd_inflate_free(&inflater);
437}
438
439void test_nghttp2_hd_inflate_clearall_inc(void) {
440  nghttp2_hd_inflater inflater;
441  nghttp2_bufs bufs;
442  ssize_t blocklen;
443  nghttp2_nv nv;
444  uint8_t value[4061];
445  nva_out out;
446  nghttp2_mem *mem;
447
448  mem = nghttp2_mem_default();
449  bufs_large_init(&bufs, 8192);
450
451  nva_out_init(&out);
452  /* Total 4097 bytes space required to hold this entry */
453  nv.name = (uint8_t *)"alpha";
454  nv.namelen = strlen((char *)nv.name);
455  memset(value, '0', sizeof(value));
456  value[sizeof(value) - 1] = '\0';
457  nv.value = value;
458  nv.valuelen = sizeof(value) - 1;
459
460  nv.flags = NGHTTP2_NV_FLAG_NONE;
461
462  nghttp2_hd_inflate_init(&inflater, mem);
463
464  CU_ASSERT(
465      0 == nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING));
466
467  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
468
469  CU_ASSERT(blocklen > 0);
470  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
471
472  CU_ASSERT(1 == out.nvlen);
473  assert_nv_equal(&nv, out.nva, 1, mem);
474  CU_ASSERT(0 == inflater.ctx.hd_table.len);
475
476  nva_out_reset(&out, mem);
477
478  /* Do it again */
479  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
480
481  CU_ASSERT(1 == out.nvlen);
482  assert_nv_equal(&nv, out.nva, 1, mem);
483  CU_ASSERT(0 == inflater.ctx.hd_table.len);
484
485  nva_out_reset(&out, mem);
486  nghttp2_bufs_reset(&bufs);
487
488  /* This time, 4096 bytes space required, which is just fits in the
489     header table */
490  nv.valuelen = sizeof(value) - 2;
491
492  CU_ASSERT(
493      0 == nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING));
494
495  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
496
497  CU_ASSERT(blocklen > 0);
498  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
499
500  CU_ASSERT(1 == out.nvlen);
501  assert_nv_equal(&nv, out.nva, 1, mem);
502  CU_ASSERT(1 == inflater.ctx.hd_table.len);
503
504  nva_out_reset(&out, mem);
505  nghttp2_bufs_reset(&bufs);
506
507  nghttp2_bufs_free(&bufs);
508  nghttp2_hd_inflate_free(&inflater);
509}
510
511void test_nghttp2_hd_inflate_zero_length_huffman(void) {
512  nghttp2_hd_inflater inflater;
513  nghttp2_bufs bufs;
514  /* Literal header without indexing - new name */
515  uint8_t data[] = {0x40, 0x01, 0x78 /* 'x' */, 0x80};
516  nva_out out;
517  nghttp2_mem *mem;
518
519  mem = nghttp2_mem_default();
520  frame_pack_bufs_init(&bufs);
521
522  nva_out_init(&out);
523
524  nghttp2_bufs_add(&bufs, data, sizeof(data));
525
526  /* /\* Literal header without indexing - new name *\/ */
527  /* ptr[0] = 0x40; */
528  /* ptr[1] = 1; */
529  /* ptr[2] = 'x'; */
530  /* ptr[3] = 0x80; */
531
532  nghttp2_hd_inflate_init(&inflater, mem);
533  CU_ASSERT(4 == inflate_hd(&inflater, &out, &bufs, 0, mem));
534
535  CU_ASSERT(1 == out.nvlen);
536  CU_ASSERT(1 == out.nva[0].namelen);
537  CU_ASSERT('x' == out.nva[0].name[0]);
538  CU_ASSERT(NULL == out.nva[0].value);
539  CU_ASSERT(0 == out.nva[0].valuelen);
540
541  nva_out_reset(&out, mem);
542  nghttp2_bufs_free(&bufs);
543  nghttp2_hd_inflate_free(&inflater);
544}
545
546void test_nghttp2_hd_inflate_expect_table_size_update(void) {
547  nghttp2_hd_inflater inflater;
548  nghttp2_bufs bufs;
549  nghttp2_mem *mem;
550  /* Indexed Header: :method: GET */
551  uint8_t data[] = {0x82};
552  nva_out out;
553
554  mem = nghttp2_mem_default();
555  frame_pack_bufs_init(&bufs);
556  nva_out_init(&out);
557
558  nghttp2_bufs_add(&bufs, data, sizeof(data));
559  nghttp2_hd_inflate_init(&inflater, mem);
560  /* This will make inflater require table size update in the next
561     inflation. */
562  nghttp2_hd_inflate_change_table_size(&inflater, 4095);
563  nghttp2_hd_inflate_change_table_size(&inflater, 4096);
564  CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
565            inflate_hd(&inflater, &out, &bufs, 0, mem));
566
567  nva_out_reset(&out, mem);
568  nghttp2_hd_inflate_free(&inflater);
569
570  /* This does not require for encoder to emit table size update since
571   * size is not changed. */
572  nghttp2_hd_inflate_init(&inflater, mem);
573  nghttp2_hd_inflate_change_table_size(&inflater, 4096);
574  CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) ==
575            inflate_hd(&inflater, &out, &bufs, 0, mem));
576
577  nva_out_reset(&out, mem);
578  nghttp2_hd_inflate_free(&inflater);
579
580  /* This does not require for encodre to emit table size update since
581     new size is larger than current size. */
582  nghttp2_hd_inflate_init(&inflater, mem);
583  nghttp2_hd_inflate_change_table_size(&inflater, 4097);
584  CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) ==
585            inflate_hd(&inflater, &out, &bufs, 0, mem));
586
587  nva_out_reset(&out, mem);
588  nghttp2_hd_inflate_free(&inflater);
589
590  /* Received table size is strictly larger than minimum table size */
591  nghttp2_hd_inflate_init(&inflater, mem);
592  nghttp2_hd_inflate_change_table_size(&inflater, 111);
593  nghttp2_hd_inflate_change_table_size(&inflater, 4096);
594
595  nghttp2_bufs_reset(&bufs);
596  nghttp2_hd_emit_table_size(&bufs, 112);
597
598  CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
599            inflate_hd(&inflater, &out, &bufs, 0, mem));
600
601  nva_out_reset(&out, mem);
602  nghttp2_hd_inflate_free(&inflater);
603
604  /* Receiving 2 table size updates, min and last value */
605  nghttp2_hd_inflate_init(&inflater, mem);
606  nghttp2_hd_inflate_change_table_size(&inflater, 111);
607  nghttp2_hd_inflate_change_table_size(&inflater, 4096);
608
609  nghttp2_bufs_reset(&bufs);
610  nghttp2_hd_emit_table_size(&bufs, 111);
611  nghttp2_hd_emit_table_size(&bufs, 4096);
612
613  CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) ==
614            inflate_hd(&inflater, &out, &bufs, 0, mem));
615
616  nva_out_reset(&out, mem);
617  nghttp2_hd_inflate_free(&inflater);
618
619  /* 2nd update is larger than last value */
620  nghttp2_hd_inflate_init(&inflater, mem);
621  nghttp2_hd_inflate_change_table_size(&inflater, 111);
622  nghttp2_hd_inflate_change_table_size(&inflater, 4095);
623
624  nghttp2_bufs_reset(&bufs);
625  nghttp2_hd_emit_table_size(&bufs, 111);
626  nghttp2_hd_emit_table_size(&bufs, 4096);
627
628  CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
629            inflate_hd(&inflater, &out, &bufs, 0, mem));
630
631  nva_out_reset(&out, mem);
632  nghttp2_hd_inflate_free(&inflater);
633
634  nghttp2_bufs_free(&bufs);
635}
636
637void test_nghttp2_hd_inflate_unexpected_table_size_update(void) {
638  nghttp2_hd_inflater inflater;
639  nghttp2_bufs bufs;
640  nghttp2_mem *mem;
641  /* Indexed Header: :method: GET, followed by table size update.
642     This violates RFC 7541. */
643  uint8_t data[] = {0x82, 0x20};
644  nva_out out;
645
646  mem = nghttp2_mem_default();
647  frame_pack_bufs_init(&bufs);
648  nva_out_init(&out);
649
650  nghttp2_bufs_add(&bufs, data, sizeof(data));
651  nghttp2_hd_inflate_init(&inflater, mem);
652  CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
653            inflate_hd(&inflater, &out, &bufs, 0, mem));
654
655  nva_out_reset(&out, mem);
656  nghttp2_bufs_free(&bufs);
657  nghttp2_hd_inflate_free(&inflater);
658}
659
660void test_nghttp2_hd_ringbuf_reserve(void) {
661  nghttp2_hd_deflater deflater;
662  nghttp2_hd_inflater inflater;
663  nghttp2_nv nv;
664  nghttp2_bufs bufs;
665  nva_out out;
666  int i;
667  ssize_t rv;
668  ssize_t blocklen;
669  nghttp2_mem *mem;
670
671  mem = nghttp2_mem_default();
672  frame_pack_bufs_init(&bufs);
673  nva_out_init(&out);
674
675  nv.flags = NGHTTP2_NV_FLAG_NONE;
676  nv.name = (uint8_t *)"a";
677  nv.namelen = strlen((const char *)nv.name);
678  nv.valuelen = 4;
679  nv.value = mem->malloc(nv.valuelen + 1, NULL);
680  memset(nv.value, 0, nv.valuelen);
681
682  nghttp2_hd_deflate_init2(&deflater, 8000, mem);
683  nghttp2_hd_inflate_init(&inflater, mem);
684
685  nghttp2_hd_inflate_change_table_size(&inflater, 8000);
686  nghttp2_hd_deflate_change_table_size(&deflater, 8000);
687
688  for (i = 0; i < 150; ++i) {
689    memcpy(nv.value, &i, sizeof(i));
690    rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv, 1);
691    blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
692
693    CU_ASSERT(0 == rv);
694    CU_ASSERT(blocklen > 0);
695
696    CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
697
698    CU_ASSERT(1 == out.nvlen);
699    assert_nv_equal(&nv, out.nva, 1, mem);
700
701    nva_out_reset(&out, mem);
702    nghttp2_bufs_reset(&bufs);
703  }
704
705  nghttp2_bufs_free(&bufs);
706  nghttp2_hd_inflate_free(&inflater);
707  nghttp2_hd_deflate_free(&deflater);
708
709  mem->free(nv.value, NULL);
710}
711
712void test_nghttp2_hd_change_table_size(void) {
713  nghttp2_hd_deflater deflater;
714  nghttp2_hd_inflater inflater;
715  nghttp2_nv nva[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
716  nghttp2_nv nva2[] = {MAKE_NV(":path", "/")};
717  nghttp2_bufs bufs;
718  ssize_t rv;
719  nva_out out;
720  ssize_t blocklen;
721  nghttp2_mem *mem;
722
723  mem = nghttp2_mem_default();
724  frame_pack_bufs_init(&bufs);
725
726  nva_out_init(&out);
727
728  nghttp2_hd_deflate_init(&deflater, mem);
729  nghttp2_hd_inflate_init(&inflater, mem);
730
731  /* inflater changes notifies 8000 max header table size */
732  CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 8000));
733  CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 8000));
734
735  CU_ASSERT(4096 == deflater.ctx.hd_table_bufsize_max);
736
737  CU_ASSERT(4096 == inflater.ctx.hd_table_bufsize_max);
738  CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
739
740  /* This will emit encoding context update with header table size 4096 */
741  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
742  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
743
744  CU_ASSERT(0 == rv);
745  CU_ASSERT(blocklen > 0);
746  CU_ASSERT(2 == deflater.ctx.hd_table.len);
747  CU_ASSERT(63 == nghttp2_hd_deflate_get_num_table_entries(&deflater));
748  CU_ASSERT(4096 == deflater.ctx.hd_table_bufsize_max);
749
750  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
751  CU_ASSERT(2 == inflater.ctx.hd_table.len);
752  CU_ASSERT(63 == nghttp2_hd_inflate_get_num_table_entries(&inflater));
753  CU_ASSERT(4096 == inflater.ctx.hd_table_bufsize_max);
754  CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
755
756  nva_out_reset(&out, mem);
757  nghttp2_bufs_reset(&bufs);
758
759  /* inflater changes header table size to 1024 */
760  CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 1024));
761  CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 1024));
762
763  CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
764
765  CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max);
766  CU_ASSERT(1024 == inflater.settings_hd_table_bufsize_max);
767
768  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
769  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
770
771  CU_ASSERT(0 == rv);
772  CU_ASSERT(blocklen > 0);
773  CU_ASSERT(2 == deflater.ctx.hd_table.len);
774  CU_ASSERT(63 == nghttp2_hd_deflate_get_num_table_entries(&deflater));
775  CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
776
777  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
778  CU_ASSERT(2 == inflater.ctx.hd_table.len);
779  CU_ASSERT(63 == nghttp2_hd_inflate_get_num_table_entries(&inflater));
780  CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max);
781  CU_ASSERT(1024 == inflater.settings_hd_table_bufsize_max);
782
783  nva_out_reset(&out, mem);
784  nghttp2_bufs_reset(&bufs);
785
786  /* inflater changes header table size to 0 */
787  CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 0));
788  CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 0));
789
790  CU_ASSERT(0 == deflater.ctx.hd_table.len);
791  CU_ASSERT(61 == nghttp2_hd_deflate_get_num_table_entries(&deflater));
792  CU_ASSERT(0 == deflater.ctx.hd_table_bufsize_max);
793
794  CU_ASSERT(0 == inflater.ctx.hd_table.len);
795  CU_ASSERT(61 == nghttp2_hd_inflate_get_num_table_entries(&inflater));
796  CU_ASSERT(0 == inflater.ctx.hd_table_bufsize_max);
797  CU_ASSERT(0 == inflater.settings_hd_table_bufsize_max);
798
799  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
800  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
801
802  CU_ASSERT(0 == rv);
803  CU_ASSERT(blocklen > 0);
804  CU_ASSERT(0 == deflater.ctx.hd_table.len);
805  CU_ASSERT(61 == nghttp2_hd_deflate_get_num_table_entries(&deflater));
806  CU_ASSERT(0 == deflater.ctx.hd_table_bufsize_max);
807
808  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
809  CU_ASSERT(0 == inflater.ctx.hd_table.len);
810  CU_ASSERT(61 == nghttp2_hd_inflate_get_num_table_entries(&inflater));
811  CU_ASSERT(0 == inflater.ctx.hd_table_bufsize_max);
812  CU_ASSERT(0 == inflater.settings_hd_table_bufsize_max);
813
814  nva_out_reset(&out, mem);
815  nghttp2_bufs_reset(&bufs);
816
817  nghttp2_bufs_free(&bufs);
818  nghttp2_hd_inflate_free(&inflater);
819  nghttp2_hd_deflate_free(&deflater);
820
821  /* Check table buffer is expanded */
822  frame_pack_bufs_init(&bufs);
823
824  nghttp2_hd_deflate_init2(&deflater, 8192, mem);
825  nghttp2_hd_inflate_init(&inflater, mem);
826
827  /* First inflater changes header table size to 8000 */
828  CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 8000));
829  CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 8000));
830
831  CU_ASSERT(8000 == deflater.ctx.hd_table_bufsize_max);
832  CU_ASSERT(8000 == nghttp2_hd_deflate_get_max_dynamic_table_size(&deflater));
833  CU_ASSERT(4096 == inflater.ctx.hd_table_bufsize_max);
834  CU_ASSERT(4096 == nghttp2_hd_inflate_get_max_dynamic_table_size(&inflater));
835  CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
836
837  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
838  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
839
840  CU_ASSERT(0 == rv);
841  CU_ASSERT(blocklen > 0);
842  CU_ASSERT(2 == deflater.ctx.hd_table.len);
843  CU_ASSERT(8000 == deflater.ctx.hd_table_bufsize_max);
844
845  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
846  CU_ASSERT(2 == inflater.ctx.hd_table.len);
847  CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max);
848  CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
849
850  nva_out_reset(&out, mem);
851  nghttp2_bufs_reset(&bufs);
852
853  CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 16383));
854  CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 16383));
855
856  CU_ASSERT(8192 == deflater.ctx.hd_table_bufsize_max);
857  CU_ASSERT(8192 == nghttp2_hd_deflate_get_max_dynamic_table_size(&deflater));
858
859  CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max);
860  CU_ASSERT(8000 == nghttp2_hd_inflate_get_max_dynamic_table_size(&inflater));
861  CU_ASSERT(16383 == inflater.settings_hd_table_bufsize_max);
862
863  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
864  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
865
866  CU_ASSERT(0 == rv);
867  CU_ASSERT(blocklen > 0);
868  CU_ASSERT(2 == deflater.ctx.hd_table.len);
869  CU_ASSERT(8192 == deflater.ctx.hd_table_bufsize_max);
870
871  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
872  CU_ASSERT(2 == inflater.ctx.hd_table.len);
873  CU_ASSERT(8192 == inflater.ctx.hd_table_bufsize_max);
874  CU_ASSERT(16383 == inflater.settings_hd_table_bufsize_max);
875
876  nva_out_reset(&out, mem);
877  nghttp2_bufs_reset(&bufs);
878
879  /* Lastly, check the error condition */
880
881  rv = nghttp2_hd_emit_table_size(&bufs, 25600);
882  CU_ASSERT(rv == 0);
883  CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
884            inflate_hd(&inflater, &out, &bufs, 0, mem));
885
886  nva_out_reset(&out, mem);
887  nghttp2_bufs_reset(&bufs);
888
889  nghttp2_hd_inflate_free(&inflater);
890  nghttp2_hd_deflate_free(&deflater);
891
892  /* Check that encoder can handle the case where its allowable buffer
893     size is less than default size, 4096 */
894  nghttp2_hd_deflate_init2(&deflater, 1024, mem);
895  nghttp2_hd_inflate_init(&inflater, mem);
896
897  CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
898
899  /* This emits context update with buffer size 1024 */
900  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
901  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
902
903  CU_ASSERT(0 == rv);
904  CU_ASSERT(blocklen > 0);
905  CU_ASSERT(2 == deflater.ctx.hd_table.len);
906  CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
907
908  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
909  CU_ASSERT(2 == inflater.ctx.hd_table.len);
910  CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max);
911  CU_ASSERT(4096 == inflater.settings_hd_table_bufsize_max);
912
913  nva_out_reset(&out, mem);
914  nghttp2_bufs_reset(&bufs);
915
916  nghttp2_hd_inflate_free(&inflater);
917  nghttp2_hd_deflate_free(&deflater);
918
919  /* Check that table size UINT32_MAX can be received */
920  nghttp2_hd_deflate_init2(&deflater, UINT32_MAX, mem);
921  nghttp2_hd_inflate_init(&inflater, mem);
922
923  CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, UINT32_MAX));
924  CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, UINT32_MAX));
925
926  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
927  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
928
929  CU_ASSERT(0 == rv);
930  CU_ASSERT(UINT32_MAX == deflater.ctx.hd_table_bufsize_max);
931
932  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
933  CU_ASSERT(UINT32_MAX == inflater.ctx.hd_table_bufsize_max);
934  CU_ASSERT(UINT32_MAX == inflater.settings_hd_table_bufsize_max);
935
936  nva_out_reset(&out, mem);
937  nghttp2_bufs_reset(&bufs);
938
939  nghttp2_hd_inflate_free(&inflater);
940  nghttp2_hd_deflate_free(&deflater);
941
942  /* Check that context update emitted twice */
943  nghttp2_hd_deflate_init2(&deflater, 4096, mem);
944  nghttp2_hd_inflate_init(&inflater, mem);
945
946  CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 0));
947  CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 3000));
948  CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 0));
949  CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 3000));
950
951  CU_ASSERT(0 == deflater.min_hd_table_bufsize_max);
952  CU_ASSERT(3000 == deflater.ctx.hd_table_bufsize_max);
953
954  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, 1);
955  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
956
957  CU_ASSERT(0 == rv);
958  CU_ASSERT(3 < blocklen);
959  CU_ASSERT(3000 == deflater.ctx.hd_table_bufsize_max);
960  CU_ASSERT(UINT32_MAX == deflater.min_hd_table_bufsize_max);
961
962  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
963  CU_ASSERT(3000 == inflater.ctx.hd_table_bufsize_max);
964  CU_ASSERT(3000 == inflater.settings_hd_table_bufsize_max);
965
966  nva_out_reset(&out, mem);
967  nghttp2_bufs_reset(&bufs);
968
969  nghttp2_hd_inflate_free(&inflater);
970  nghttp2_hd_deflate_free(&deflater);
971
972  nghttp2_bufs_free(&bufs);
973}
974
975static void check_deflate_inflate(nghttp2_hd_deflater *deflater,
976                                  nghttp2_hd_inflater *inflater,
977                                  nghttp2_nv *nva, size_t nvlen,
978                                  nghttp2_mem *mem) {
979  nghttp2_bufs bufs;
980  ssize_t blocklen;
981  nva_out out;
982  int rv;
983
984  frame_pack_bufs_init(&bufs);
985
986  nva_out_init(&out);
987  rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nva, nvlen);
988  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
989
990  CU_ASSERT(0 == rv);
991  CU_ASSERT(blocklen >= 0);
992
993  CU_ASSERT(blocklen == inflate_hd(inflater, &out, &bufs, 0, mem));
994
995  CU_ASSERT(nvlen == out.nvlen);
996  assert_nv_equal(nva, out.nva, nvlen, mem);
997
998  nva_out_reset(&out, mem);
999  nghttp2_bufs_free(&bufs);
1000}
1001
1002void test_nghttp2_hd_deflate_inflate(void) {
1003  nghttp2_hd_deflater deflater;
1004  nghttp2_hd_inflater inflater;
1005  nghttp2_nv nv1[] = {
1006      MAKE_NV(":status", "200 OK"),
1007      MAKE_NV("access-control-allow-origin", "*"),
1008      MAKE_NV("cache-control", "private, max-age=0, must-revalidate"),
1009      MAKE_NV("content-length", "76073"),
1010      MAKE_NV("content-type", "text/html"),
1011      MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1012      MAKE_NV("expires", "Sat, 27 Jul 2013 06:22:12 GMT"),
1013      MAKE_NV("server", "Apache"),
1014      MAKE_NV("vary", "foobar"),
1015      MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1016      MAKE_NV("x-cache", "MISS from alphabravo"),
1017      MAKE_NV("x-cache-action", "MISS"),
1018      MAKE_NV("x-cache-age", "0"),
1019      MAKE_NV("x-cache-lookup", "MISS from alphabravo:3128"),
1020      MAKE_NV("x-lb-nocache", "true"),
1021  };
1022  nghttp2_nv nv2[] = {
1023      MAKE_NV(":status", "304 Not Modified"),
1024      MAKE_NV("age", "0"),
1025      MAKE_NV("cache-control", "max-age=56682045"),
1026      MAKE_NV("content-type", "text/css"),
1027      MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1028      MAKE_NV("expires", "Thu, 14 May 2015 07:22:57 GMT"),
1029      MAKE_NV("last-modified", "Tue, 14 May 2013 07:22:15 GMT"),
1030      MAKE_NV("vary", "Accept-Encoding"),
1031      MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1032      MAKE_NV("x-cache", "HIT from alphabravo"),
1033      MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128")};
1034  nghttp2_nv nv3[] = {
1035      MAKE_NV(":status", "304 Not Modified"),
1036      MAKE_NV("age", "0"),
1037      MAKE_NV("cache-control", "max-age=56682072"),
1038      MAKE_NV("content-type", "text/css"),
1039      MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1040      MAKE_NV("expires", "Thu, 14 May 2015 07:23:24 GMT"),
1041      MAKE_NV("last-modified", "Tue, 14 May 2013 07:22:13 GMT"),
1042      MAKE_NV("vary", "Accept-Encoding"),
1043      MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1044      MAKE_NV("x-cache", "HIT from alphabravo"),
1045      MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1046  };
1047  nghttp2_nv nv4[] = {
1048      MAKE_NV(":status", "304 Not Modified"),
1049      MAKE_NV("age", "0"),
1050      MAKE_NV("cache-control", "max-age=56682022"),
1051      MAKE_NV("content-type", "text/css"),
1052      MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1053      MAKE_NV("expires", "Thu, 14 May 2015 07:22:34 GMT"),
1054      MAKE_NV("last-modified", "Tue, 14 May 2013 07:22:14 GMT"),
1055      MAKE_NV("vary", "Accept-Encoding"),
1056      MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1057      MAKE_NV("x-cache", "HIT from alphabravo"),
1058      MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1059  };
1060  nghttp2_nv nv5[] = {
1061      MAKE_NV(":status", "304 Not Modified"),
1062      MAKE_NV("age", "0"),
1063      MAKE_NV("cache-control", "max-age=4461139"),
1064      MAKE_NV("content-type", "application/x-javascript"),
1065      MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1066      MAKE_NV("expires", "Mon, 16 Sep 2013 21:34:31 GMT"),
1067      MAKE_NV("last-modified", "Thu, 05 May 2011 09:15:59 GMT"),
1068      MAKE_NV("vary", "Accept-Encoding"),
1069      MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1070      MAKE_NV("x-cache", "HIT from alphabravo"),
1071      MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1072  };
1073  nghttp2_nv nv6[] = {
1074      MAKE_NV(":status", "304 Not Modified"),
1075      MAKE_NV("age", "0"),
1076      MAKE_NV("cache-control", "max-age=18645951"),
1077      MAKE_NV("content-type", "application/x-javascript"),
1078      MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1079      MAKE_NV("expires", "Fri, 28 Feb 2014 01:48:03 GMT"),
1080      MAKE_NV("last-modified", "Tue, 12 Jul 2011 16:02:59 GMT"),
1081      MAKE_NV("vary", "Accept-Encoding"),
1082      MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1083      MAKE_NV("x-cache", "HIT from alphabravo"),
1084      MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1085  };
1086  nghttp2_nv nv7[] = {
1087      MAKE_NV(":status", "304 Not Modified"),
1088      MAKE_NV("age", "0"),
1089      MAKE_NV("cache-control", "max-age=31536000"),
1090      MAKE_NV("content-type", "application/javascript"),
1091      MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1092      MAKE_NV("etag", "\"6807-4dc5b54e0dcc0\""),
1093      MAKE_NV("expires", "Wed, 21 May 2014 08:32:17 GMT"),
1094      MAKE_NV("last-modified", "Fri, 10 May 2013 11:18:51 GMT"),
1095      MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1096      MAKE_NV("x-cache", "HIT from alphabravo"),
1097      MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1098  };
1099  nghttp2_nv nv8[] = {
1100      MAKE_NV(":status", "304 Not Modified"),
1101      MAKE_NV("age", "0"),
1102      MAKE_NV("cache-control", "max-age=31536000"),
1103      MAKE_NV("content-type", "application/javascript"),
1104      MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1105      MAKE_NV("etag", "\"41c6-4de7d28585b00\""),
1106      MAKE_NV("expires", "Thu, 12 Jun 2014 10:00:58 GMT"),
1107      MAKE_NV("last-modified", "Thu, 06 Jun 2013 14:30:36 GMT"),
1108      MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1109      MAKE_NV("x-cache", "HIT from alphabravo"),
1110      MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1111  };
1112  nghttp2_nv nv9[] = {
1113      MAKE_NV(":status", "304 Not Modified"),
1114      MAKE_NV("age", "0"),
1115      MAKE_NV("cache-control", "max-age=31536000"),
1116      MAKE_NV("content-type", "application/javascript"),
1117      MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1118      MAKE_NV("etag", "\"19d6e-4dc5b35a541c0\""),
1119      MAKE_NV("expires", "Wed, 21 May 2014 08:32:18 GMT"),
1120      MAKE_NV("last-modified", "Fri, 10 May 2013 11:10:07 GMT"),
1121      MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1122      MAKE_NV("x-cache", "HIT from alphabravo"),
1123      MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1124  };
1125  nghttp2_nv nv10[] = {
1126      MAKE_NV(":status", "304 Not Modified"),
1127      MAKE_NV("age", "0"),
1128      MAKE_NV("cache-control", "max-age=56682045"),
1129      MAKE_NV("content-type", "text/css"),
1130      MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1131      MAKE_NV("expires", "Thu, 14 May 2015 07:22:57 GMT"),
1132      MAKE_NV("last-modified", "Tue, 14 May 2013 07:21:53 GMT"),
1133      MAKE_NV("vary", "Accept-Encoding"),
1134      MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1135      MAKE_NV("x-cache", "HIT from alphabravo"),
1136      MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1137  };
1138  nghttp2_mem *mem;
1139
1140  mem = nghttp2_mem_default();
1141
1142  nghttp2_hd_deflate_init(&deflater, mem);
1143  nghttp2_hd_inflate_init(&inflater, mem);
1144
1145  check_deflate_inflate(&deflater, &inflater, nv1, ARRLEN(nv1), mem);
1146  check_deflate_inflate(&deflater, &inflater, nv2, ARRLEN(nv2), mem);
1147  check_deflate_inflate(&deflater, &inflater, nv3, ARRLEN(nv3), mem);
1148  check_deflate_inflate(&deflater, &inflater, nv4, ARRLEN(nv4), mem);
1149  check_deflate_inflate(&deflater, &inflater, nv5, ARRLEN(nv5), mem);
1150  check_deflate_inflate(&deflater, &inflater, nv6, ARRLEN(nv6), mem);
1151  check_deflate_inflate(&deflater, &inflater, nv7, ARRLEN(nv7), mem);
1152  check_deflate_inflate(&deflater, &inflater, nv8, ARRLEN(nv8), mem);
1153  check_deflate_inflate(&deflater, &inflater, nv9, ARRLEN(nv9), mem);
1154  check_deflate_inflate(&deflater, &inflater, nv10, ARRLEN(nv10), mem);
1155
1156  nghttp2_hd_inflate_free(&inflater);
1157  nghttp2_hd_deflate_free(&deflater);
1158}
1159
1160void test_nghttp2_hd_no_index(void) {
1161  nghttp2_hd_deflater deflater;
1162  nghttp2_hd_inflater inflater;
1163  nghttp2_bufs bufs;
1164  ssize_t blocklen;
1165  nghttp2_nv nva[] = {
1166      MAKE_NV(":method", "GET"), MAKE_NV(":method", "POST"),
1167      MAKE_NV(":path", "/foo"),  MAKE_NV("version", "HTTP/1.1"),
1168      MAKE_NV(":method", "GET"),
1169  };
1170  size_t i;
1171  nva_out out;
1172  int rv;
1173  nghttp2_mem *mem;
1174
1175  mem = nghttp2_mem_default();
1176
1177  /* 1st :method: GET can be indexable, last one is not */
1178  for (i = 1; i < ARRLEN(nva); ++i) {
1179    nva[i].flags = NGHTTP2_NV_FLAG_NO_INDEX;
1180  }
1181
1182  frame_pack_bufs_init(&bufs);
1183
1184  nva_out_init(&out);
1185
1186  nghttp2_hd_deflate_init(&deflater, mem);
1187  nghttp2_hd_inflate_init(&inflater, mem);
1188
1189  rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, ARRLEN(nva));
1190  blocklen = (ssize_t)nghttp2_bufs_len(&bufs);
1191
1192  CU_ASSERT(0 == rv);
1193  CU_ASSERT(blocklen > 0);
1194  CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
1195
1196  CU_ASSERT(ARRLEN(nva) == out.nvlen);
1197  assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1198
1199  CU_ASSERT(out.nva[0].flags == NGHTTP2_NV_FLAG_NONE);
1200  for (i = 1; i < ARRLEN(nva); ++i) {
1201    CU_ASSERT(out.nva[i].flags == NGHTTP2_NV_FLAG_NO_INDEX);
1202  }
1203
1204  nva_out_reset(&out, mem);
1205
1206  nghttp2_bufs_free(&bufs);
1207  nghttp2_hd_inflate_free(&inflater);
1208  nghttp2_hd_deflate_free(&deflater);
1209}
1210
1211void test_nghttp2_hd_deflate_bound(void) {
1212  nghttp2_hd_deflater deflater;
1213  nghttp2_nv nva[] = {MAKE_NV(":method", "GET"), MAKE_NV("alpha", "bravo")};
1214  nghttp2_bufs bufs;
1215  size_t bound, bound2;
1216  nghttp2_mem *mem;
1217
1218  mem = nghttp2_mem_default();
1219  frame_pack_bufs_init(&bufs);
1220
1221  nghttp2_hd_deflate_init(&deflater, mem);
1222
1223  bound = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva));
1224
1225  CU_ASSERT(12 + 6 * 2 * 2 + nva[0].namelen + nva[0].valuelen + nva[1].namelen +
1226                nva[1].valuelen ==
1227            bound);
1228
1229  nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, ARRLEN(nva));
1230
1231  CU_ASSERT(bound > (size_t)nghttp2_bufs_len(&bufs));
1232
1233  bound2 = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva));
1234
1235  CU_ASSERT(bound == bound2);
1236
1237  nghttp2_bufs_free(&bufs);
1238  nghttp2_hd_deflate_free(&deflater);
1239}
1240
1241void test_nghttp2_hd_public_api(void) {
1242  nghttp2_hd_deflater *deflater;
1243  nghttp2_hd_inflater *inflater;
1244  nghttp2_nv nva[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
1245  uint8_t buf[4096];
1246  size_t buflen;
1247  ssize_t blocklen;
1248  nghttp2_bufs bufs;
1249  nghttp2_mem *mem;
1250
1251  mem = nghttp2_mem_default();
1252
1253  CU_ASSERT(0 == nghttp2_hd_deflate_new(&deflater, 4096));
1254  CU_ASSERT(0 == nghttp2_hd_inflate_new(&inflater));
1255
1256  buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1257
1258  blocklen = nghttp2_hd_deflate_hd(deflater, buf, buflen, nva, ARRLEN(nva));
1259
1260  CU_ASSERT(blocklen > 0);
1261
1262  nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1263  bufs.head->buf.last += blocklen;
1264
1265  CU_ASSERT(blocklen == inflate_hd(inflater, NULL, &bufs, 0, mem));
1266
1267  nghttp2_bufs_wrap_free(&bufs);
1268
1269  nghttp2_hd_inflate_del(inflater);
1270  nghttp2_hd_deflate_del(deflater);
1271
1272  /* See NGHTTP2_ERR_INSUFF_BUFSIZE */
1273  CU_ASSERT(0 == nghttp2_hd_deflate_new(&deflater, 4096));
1274
1275  blocklen = nghttp2_hd_deflate_hd(deflater, buf, (size_t)(blocklen - 1), nva,
1276                                   ARRLEN(nva));
1277
1278  CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == blocklen);
1279
1280  nghttp2_hd_deflate_del(deflater);
1281}
1282
1283void test_nghttp2_hd_deflate_hd_vec(void) {
1284  nghttp2_hd_deflater *deflater;
1285  nghttp2_hd_inflater *inflater;
1286  nghttp2_nv nva[] = {
1287      MAKE_NV(":method", "PUT"),
1288      MAKE_NV(":scheme", "https"),
1289      MAKE_NV(":authority", "localhost:3000"),
1290      MAKE_NV(":path", "/usr/foo/alpha/bravo"),
1291      MAKE_NV("content-type", "image/png"),
1292      MAKE_NV("content-length", "1000000007"),
1293  };
1294  uint8_t buf[4096];
1295  ssize_t blocklen;
1296  nghttp2_mem *mem;
1297  nghttp2_vec vec[256];
1298  size_t buflen;
1299  nghttp2_bufs bufs;
1300  nva_out out;
1301  size_t i;
1302
1303  mem = nghttp2_mem_default();
1304
1305  nva_out_init(&out);
1306
1307  nghttp2_hd_deflate_new(&deflater, 4096);
1308  nghttp2_hd_inflate_new(&inflater);
1309
1310  buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1311
1312  vec[0].base = &buf[0];
1313  vec[0].len = buflen / 2;
1314  vec[1].base = &buf[buflen / 2];
1315  vec[1].len = buflen / 2;
1316
1317  blocklen = nghttp2_hd_deflate_hd_vec(deflater, vec, 2, nva, ARRLEN(nva));
1318
1319  CU_ASSERT(blocklen > 0);
1320
1321  nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1322  bufs.head->buf.last += blocklen;
1323
1324  CU_ASSERT(blocklen == inflate_hd(inflater, &out, &bufs, 0, mem));
1325
1326  CU_ASSERT(ARRLEN(nva) == out.nvlen);
1327  assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1328
1329  nghttp2_bufs_wrap_free(&bufs);
1330
1331  nghttp2_hd_inflate_del(inflater);
1332  nghttp2_hd_deflate_del(deflater);
1333  nva_out_reset(&out, mem);
1334
1335  /* check the case when veclen is 0 */
1336  nghttp2_hd_deflate_new(&deflater, 4096);
1337  nghttp2_hd_inflate_new(&inflater);
1338
1339  blocklen = nghttp2_hd_deflate_hd_vec(deflater, NULL, 0, nva, ARRLEN(nva));
1340
1341  CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == blocklen);
1342
1343  nghttp2_hd_inflate_del(inflater);
1344  nghttp2_hd_deflate_del(deflater);
1345
1346  /* check the case when chunk length is 0 */
1347  vec[0].base = NULL;
1348  vec[0].len = 0;
1349  vec[1].base = NULL;
1350  vec[1].len = 0;
1351
1352  nghttp2_hd_deflate_new(&deflater, 4096);
1353  nghttp2_hd_inflate_new(&inflater);
1354
1355  blocklen = nghttp2_hd_deflate_hd_vec(deflater, vec, 2, nva, ARRLEN(nva));
1356
1357  CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == blocklen);
1358
1359  nghttp2_hd_inflate_del(inflater);
1360  nghttp2_hd_deflate_del(deflater);
1361
1362  /* check the case where chunk size differs in each chunk */
1363  nghttp2_hd_deflate_new(&deflater, 4096);
1364  nghttp2_hd_inflate_new(&inflater);
1365
1366  buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1367
1368  vec[0].base = &buf[0];
1369  vec[0].len = buflen / 2;
1370  vec[1].base = &buf[buflen / 2];
1371  vec[1].len = (buflen / 2) + 1;
1372
1373  blocklen = nghttp2_hd_deflate_hd_vec(deflater, vec, 2, nva, ARRLEN(nva));
1374
1375  CU_ASSERT(blocklen > 0);
1376
1377  nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1378  bufs.head->buf.last += blocklen;
1379
1380  CU_ASSERT(blocklen == inflate_hd(inflater, &out, &bufs, 0, mem));
1381  CU_ASSERT(ARRLEN(nva) == out.nvlen);
1382  assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1383
1384  nghttp2_bufs_wrap_free(&bufs);
1385
1386  nghttp2_hd_inflate_del(inflater);
1387  nghttp2_hd_deflate_del(deflater);
1388  nva_out_reset(&out, mem);
1389
1390  /* check the case where chunk size is 1 */
1391  nghttp2_hd_deflate_new(&deflater, 4096);
1392  nghttp2_hd_inflate_new(&inflater);
1393
1394  buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1395
1396  assert(buflen <= ARRLEN(vec));
1397
1398  for (i = 0; i < buflen; ++i) {
1399    vec[i].base = &buf[i];
1400    vec[i].len = 1;
1401  }
1402
1403  blocklen = nghttp2_hd_deflate_hd_vec(deflater, vec, buflen, nva, ARRLEN(nva));
1404
1405  CU_ASSERT(blocklen > 0);
1406
1407  nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1408  bufs.head->buf.last += blocklen;
1409
1410  CU_ASSERT(blocklen == inflate_hd(inflater, &out, &bufs, 0, mem));
1411  CU_ASSERT(ARRLEN(nva) == out.nvlen);
1412  assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1413
1414  nghttp2_bufs_wrap_free(&bufs);
1415
1416  nghttp2_hd_inflate_del(inflater);
1417  nghttp2_hd_deflate_del(deflater);
1418  nva_out_reset(&out, mem);
1419}
1420
1421static size_t encode_length(uint8_t *buf, uint64_t n, size_t prefix) {
1422  size_t k = (size_t)((1 << prefix) - 1);
1423  size_t len = 0;
1424  *buf = (uint8_t)(*buf & ~k);
1425  if (n >= k) {
1426    *buf = (uint8_t)(*buf | k);
1427    ++buf;
1428    n -= k;
1429    ++len;
1430  } else {
1431    *buf = (uint8_t)(*buf | n);
1432    ++buf;
1433    return 1;
1434  }
1435  do {
1436    ++len;
1437    if (n >= 128) {
1438      *buf = (uint8_t)((1 << 7) | (n & 0x7f));
1439      ++buf;
1440      n >>= 7;
1441    } else {
1442      *buf++ = (uint8_t)n;
1443      break;
1444    }
1445  } while (n);
1446  return len;
1447}
1448
1449void test_nghttp2_hd_decode_length(void) {
1450  uint32_t out;
1451  size_t shift;
1452  int fin;
1453  uint8_t buf[16];
1454  uint8_t *bufp;
1455  size_t len;
1456  ssize_t rv;
1457  size_t i;
1458
1459  memset(buf, 0, sizeof(buf));
1460  len = encode_length(buf, UINT32_MAX, 7);
1461
1462  rv = nghttp2_hd_decode_length(&out, &shift, &fin, 0, 0, buf, buf + len, 7);
1463
1464  CU_ASSERT((ssize_t)len == rv);
1465  CU_ASSERT(0 != fin);
1466  CU_ASSERT(UINT32_MAX == out);
1467
1468  /* Make sure that we can decode integer if we feed 1 byte at a
1469     time */
1470  out = 0;
1471  shift = 0;
1472  fin = 0;
1473  bufp = buf;
1474
1475  for (i = 0; i < len; ++i, ++bufp) {
1476    rv = nghttp2_hd_decode_length(&out, &shift, &fin, out, shift, bufp,
1477                                  bufp + 1, 7);
1478
1479    CU_ASSERT(rv == 1);
1480
1481    if (fin) {
1482      break;
1483    }
1484  }
1485
1486  CU_ASSERT(i == len - 1);
1487  CU_ASSERT(0 != fin);
1488  CU_ASSERT(UINT32_MAX == out);
1489
1490  /* Check overflow case */
1491  memset(buf, 0, sizeof(buf));
1492  len = encode_length(buf, 1ll << 32, 7);
1493
1494  rv = nghttp2_hd_decode_length(&out, &shift, &fin, 0, 0, buf, buf + len, 7);
1495
1496  CU_ASSERT(-1 == rv);
1497
1498  /* Check the case that shift goes beyond 32 bits */
1499  buf[0] = 255;
1500  buf[1] = 128;
1501  buf[2] = 128;
1502  buf[3] = 128;
1503  buf[4] = 128;
1504  buf[5] = 128;
1505  buf[6] = 1;
1506
1507  rv = nghttp2_hd_decode_length(&out, &shift, &fin, 0, 0, buf, buf + 7, 8);
1508
1509  CU_ASSERT(-1 == rv);
1510}
1511
1512void test_nghttp2_hd_huff_encode(void) {
1513  int rv;
1514  ssize_t len;
1515  nghttp2_buf outbuf;
1516  nghttp2_bufs bufs;
1517  nghttp2_hd_huff_decode_context ctx;
1518  const uint8_t t1[] = {22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
1519                        10, 9,  8,  7,  6,  5,  4,  3,  2,  1,  0};
1520  uint8_t b[256];
1521
1522  nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1523  frame_pack_bufs_init(&bufs);
1524
1525  rv = nghttp2_hd_huff_encode(&bufs, t1, sizeof(t1));
1526
1527  CU_ASSERT(rv == 0);
1528
1529  nghttp2_hd_huff_decode_context_init(&ctx);
1530
1531  len = nghttp2_hd_huff_decode(&ctx, &outbuf, bufs.cur->buf.pos,
1532                               nghttp2_bufs_len(&bufs), 1);
1533
1534  CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == len);
1535  CU_ASSERT((ssize_t)sizeof(t1) == nghttp2_buf_len(&outbuf));
1536
1537  CU_ASSERT(0 == memcmp(t1, outbuf.pos, sizeof(t1)));
1538
1539  nghttp2_bufs_free(&bufs);
1540}
1541
1542void test_nghttp2_hd_huff_decode(void) {
1543  const uint8_t e[] = {0x1f, 0xff, 0xff, 0xff, 0xff, 0xff};
1544  nghttp2_hd_huff_decode_context ctx;
1545  nghttp2_buf outbuf;
1546  uint8_t b[256];
1547  ssize_t len;
1548
1549  nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1550  nghttp2_hd_huff_decode_context_init(&ctx);
1551  len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 1, 1);
1552
1553  CU_ASSERT(1 == len);
1554  CU_ASSERT(0 == memcmp("a", outbuf.pos, 1));
1555
1556  /* Premature sequence must elicit decoding error */
1557  nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1558  nghttp2_hd_huff_decode_context_init(&ctx);
1559  len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 2, 1);
1560
1561  CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == len);
1562
1563  /* Fully decoding EOS is error */
1564  nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1565  nghttp2_hd_huff_decode_context_init(&ctx);
1566  len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 2, 6);
1567
1568  CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == len);
1569
1570  /* Check failure state */
1571  nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1572  nghttp2_hd_huff_decode_context_init(&ctx);
1573  len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 5, 0);
1574
1575  CU_ASSERT(5 == len);
1576  CU_ASSERT(nghttp2_hd_huff_decode_failure_state(&ctx));
1577}
1578