Imported Upstream version 1.0.0
[platform/upstream/nghttp2.git] / tests / nghttp2_hd_test.c
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
36 #define GET_TABLE_ENT(context, index) nghttp2_hd_table_get(context, index)
37
38 void test_nghttp2_hd_deflate(void) {
39   nghttp2_hd_deflater deflater;
40   nghttp2_hd_inflater inflater;
41   nghttp2_nv nva1[] = {MAKE_NV(":path", "/my-example/index.html"),
42                        MAKE_NV(":scheme", "https"), MAKE_NV("hello", "world")};
43   nghttp2_nv nva2[] = {MAKE_NV(":path", "/script.js"),
44                        MAKE_NV(":scheme", "https")};
45   nghttp2_nv nva3[] = {MAKE_NV("cookie", "k1=v1"), MAKE_NV("cookie", "k2=v2"),
46                        MAKE_NV("via", "proxy")};
47   nghttp2_nv nva4[] = {MAKE_NV(":path", "/style.css"),
48                        MAKE_NV("cookie", "k1=v1"), MAKE_NV("cookie", "k1=v1")};
49   nghttp2_nv nva5[] = {MAKE_NV(":path", "/style.css"),
50                        MAKE_NV("x-nghttp2", "")};
51   nghttp2_bufs bufs;
52   ssize_t blocklen;
53   nva_out out;
54   int rv;
55   nghttp2_mem *mem;
56
57   mem = nghttp2_mem_default();
58   frame_pack_bufs_init(&bufs);
59
60   nva_out_init(&out);
61   CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater, mem));
62   CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater, mem));
63
64   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva1, ARRLEN(nva1));
65   blocklen = nghttp2_bufs_len(&bufs);
66
67   CU_ASSERT(0 == rv);
68   CU_ASSERT(blocklen > 0);
69   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
70
71   CU_ASSERT(3 == out.nvlen);
72   assert_nv_equal(nva1, out.nva, 3, mem);
73
74   nva_out_reset(&out, mem);
75   nghttp2_bufs_reset(&bufs);
76
77   /* Second headers */
78   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, ARRLEN(nva2));
79   blocklen = nghttp2_bufs_len(&bufs);
80
81   CU_ASSERT(0 == rv);
82   CU_ASSERT(blocklen > 0);
83   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
84
85   CU_ASSERT(2 == out.nvlen);
86   assert_nv_equal(nva2, out.nva, 2, mem);
87
88   nva_out_reset(&out, mem);
89   nghttp2_bufs_reset(&bufs);
90
91   /* Third headers, including same header field name, but value is not
92      the same. */
93   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva3, ARRLEN(nva3));
94   blocklen = nghttp2_bufs_len(&bufs);
95
96   CU_ASSERT(0 == rv);
97   CU_ASSERT(blocklen > 0);
98   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
99
100   CU_ASSERT(3 == out.nvlen);
101   assert_nv_equal(nva3, out.nva, 3, mem);
102
103   nva_out_reset(&out, mem);
104   nghttp2_bufs_reset(&bufs);
105
106   /* Fourth headers, including duplicate header fields. */
107   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva4, ARRLEN(nva4));
108   blocklen = nghttp2_bufs_len(&bufs);
109
110   CU_ASSERT(0 == rv);
111   CU_ASSERT(blocklen > 0);
112   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
113
114   CU_ASSERT(3 == out.nvlen);
115   assert_nv_equal(nva4, out.nva, 3, mem);
116
117   nva_out_reset(&out, mem);
118   nghttp2_bufs_reset(&bufs);
119
120   /* Fifth headers includes empty value */
121   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva5, ARRLEN(nva5));
122   blocklen = nghttp2_bufs_len(&bufs);
123
124   CU_ASSERT(0 == rv);
125   CU_ASSERT(blocklen > 0);
126   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
127
128   CU_ASSERT(2 == out.nvlen);
129   assert_nv_equal(nva5, out.nva, 2, mem);
130
131   nva_out_reset(&out, mem);
132   nghttp2_bufs_reset(&bufs);
133
134   /* Cleanup */
135   nghttp2_bufs_free(&bufs);
136   nghttp2_hd_inflate_free(&inflater);
137   nghttp2_hd_deflate_free(&deflater);
138 }
139
140 void test_nghttp2_hd_deflate_same_indexed_repr(void) {
141   nghttp2_hd_deflater deflater;
142   nghttp2_hd_inflater inflater;
143   nghttp2_nv nva1[] = {MAKE_NV("host", "alpha"), MAKE_NV("host", "alpha")};
144   nghttp2_nv nva2[] = {MAKE_NV("host", "alpha"), MAKE_NV("host", "alpha"),
145                        MAKE_NV("host", "alpha")};
146   nghttp2_bufs bufs;
147   ssize_t blocklen;
148   nva_out out;
149   int rv;
150   nghttp2_mem *mem;
151
152   mem = nghttp2_mem_default();
153   frame_pack_bufs_init(&bufs);
154
155   nva_out_init(&out);
156   CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater, mem));
157   CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater, mem));
158
159   /* Encode 2 same headers.  Emit 1 literal reprs and 1 index repr. */
160   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva1, ARRLEN(nva1));
161   blocklen = nghttp2_bufs_len(&bufs);
162
163   CU_ASSERT(0 == rv);
164   CU_ASSERT(blocklen > 0);
165   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
166
167   CU_ASSERT(2 == out.nvlen);
168   assert_nv_equal(nva1, out.nva, 2, mem);
169
170   nva_out_reset(&out, mem);
171   nghttp2_bufs_reset(&bufs);
172
173   /* Encode 3 same headers.  This time, emits 3 index reprs. */
174   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, ARRLEN(nva2));
175   blocklen = nghttp2_bufs_len(&bufs);
176
177   CU_ASSERT(0 == rv);
178   CU_ASSERT(blocklen == 3);
179   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
180
181   CU_ASSERT(3 == out.nvlen);
182   assert_nv_equal(nva2, out.nva, 3, mem);
183
184   nva_out_reset(&out, mem);
185   nghttp2_bufs_reset(&bufs);
186
187   /* Cleanup */
188   nghttp2_bufs_free(&bufs);
189   nghttp2_hd_inflate_free(&inflater);
190   nghttp2_hd_deflate_free(&deflater);
191 }
192
193 void test_nghttp2_hd_inflate_indexed(void) {
194   nghttp2_hd_inflater inflater;
195   nghttp2_bufs bufs;
196   ssize_t blocklen;
197   nghttp2_nv nv = MAKE_NV(":path", "/");
198   nva_out out;
199   nghttp2_mem *mem;
200
201   mem = nghttp2_mem_default();
202   frame_pack_bufs_init(&bufs);
203
204   nva_out_init(&out);
205   nghttp2_hd_inflate_init(&inflater, mem);
206
207   nghttp2_bufs_addb(&bufs, (1 << 7) | 4);
208
209   blocklen = nghttp2_bufs_len(&bufs);
210
211   CU_ASSERT(1 == blocklen);
212   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
213
214   CU_ASSERT(1 == out.nvlen);
215
216   assert_nv_equal(&nv, out.nva, 1, mem);
217
218   nva_out_reset(&out, mem);
219   nghttp2_bufs_reset(&bufs);
220
221   /* index = 0 is error */
222   nghttp2_bufs_addb(&bufs, 1 << 7);
223
224   blocklen = nghttp2_bufs_len(&bufs);
225
226   CU_ASSERT(1 == blocklen);
227   CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
228             inflate_hd(&inflater, &out, &bufs, 0, mem));
229
230   nghttp2_bufs_free(&bufs);
231   nghttp2_hd_inflate_free(&inflater);
232 }
233
234 void test_nghttp2_hd_inflate_indname_noinc(void) {
235   nghttp2_hd_inflater inflater;
236   nghttp2_bufs bufs;
237   ssize_t blocklen;
238   nghttp2_nv nv[] = {/* Huffman */
239                      MAKE_NV("user-agent", "nghttp2"),
240                      /* Expecting no huffman */
241                      MAKE_NV("user-agent", "x")};
242   size_t i;
243   nva_out out;
244   nghttp2_mem *mem;
245
246   mem = nghttp2_mem_default();
247   frame_pack_bufs_init(&bufs);
248
249   nva_out_init(&out);
250   nghttp2_hd_inflate_init(&inflater, mem);
251
252   for (i = 0; i < ARRLEN(nv); ++i) {
253     CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 57, &nv[i],
254                                                  NGHTTP2_HD_WITHOUT_INDEXING));
255
256     blocklen = nghttp2_bufs_len(&bufs);
257
258     CU_ASSERT(blocklen > 0);
259     CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
260
261     CU_ASSERT(1 == out.nvlen);
262     assert_nv_equal(&nv[i], out.nva, 1, mem);
263     CU_ASSERT(0 == inflater.ctx.hd_table.len);
264
265     nva_out_reset(&out, mem);
266     nghttp2_bufs_reset(&bufs);
267   }
268
269   nghttp2_bufs_free(&bufs);
270   nghttp2_hd_inflate_free(&inflater);
271 }
272
273 void test_nghttp2_hd_inflate_indname_inc(void) {
274   nghttp2_hd_inflater inflater;
275   nghttp2_bufs bufs;
276   ssize_t blocklen;
277   nghttp2_nv nv = MAKE_NV("user-agent", "nghttp2");
278   nva_out out;
279   nghttp2_mem *mem;
280
281   mem = nghttp2_mem_default();
282   frame_pack_bufs_init(&bufs);
283
284   nva_out_init(&out);
285   nghttp2_hd_inflate_init(&inflater, mem);
286
287   CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 57, &nv,
288                                                NGHTTP2_HD_WITH_INDEXING));
289
290   blocklen = nghttp2_bufs_len(&bufs);
291
292   CU_ASSERT(blocklen > 0);
293   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
294
295   CU_ASSERT(1 == out.nvlen);
296   assert_nv_equal(&nv, out.nva, 1, mem);
297   CU_ASSERT(1 == inflater.ctx.hd_table.len);
298   assert_nv_equal(
299       &nv, &GET_TABLE_ENT(&inflater.ctx, NGHTTP2_STATIC_TABLE_LENGTH +
300                                              inflater.ctx.hd_table.len - 1)->nv,
301       1, mem);
302
303   nva_out_reset(&out, mem);
304   nghttp2_bufs_free(&bufs);
305   nghttp2_hd_inflate_free(&inflater);
306 }
307
308 void test_nghttp2_hd_inflate_indname_inc_eviction(void) {
309   nghttp2_hd_inflater inflater;
310   nghttp2_bufs bufs;
311   ssize_t blocklen;
312   uint8_t value[1025];
313   nva_out out;
314   nghttp2_nv nv;
315   nghttp2_mem *mem;
316
317   mem = nghttp2_mem_default();
318   frame_pack_bufs_init(&bufs);
319
320   nva_out_init(&out);
321   nghttp2_hd_inflate_init(&inflater, mem);
322
323   memset(value, '0', sizeof(value));
324   value[sizeof(value) - 1] = '\0';
325   nv.value = value;
326   nv.valuelen = sizeof(value) - 1;
327
328   nv.flags = NGHTTP2_NV_FLAG_NONE;
329
330   CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 14, &nv,
331                                                NGHTTP2_HD_WITH_INDEXING));
332   CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 15, &nv,
333                                                NGHTTP2_HD_WITH_INDEXING));
334   CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 16, &nv,
335                                                NGHTTP2_HD_WITH_INDEXING));
336   CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 17, &nv,
337                                                NGHTTP2_HD_WITH_INDEXING));
338
339   blocklen = nghttp2_bufs_len(&bufs);
340
341   CU_ASSERT(blocklen > 0);
342
343   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
344
345   CU_ASSERT(4 == out.nvlen);
346   CU_ASSERT(14 == out.nva[0].namelen);
347   CU_ASSERT(0 == memcmp("accept-charset", out.nva[0].name, out.nva[0].namelen));
348   CU_ASSERT(sizeof(value) - 1 == out.nva[0].valuelen);
349
350   nva_out_reset(&out, mem);
351   nghttp2_bufs_reset(&bufs);
352
353   CU_ASSERT(3 == inflater.ctx.hd_table.len);
354
355   nghttp2_bufs_free(&bufs);
356   nghttp2_hd_inflate_free(&inflater);
357 }
358
359 void test_nghttp2_hd_inflate_newname_noinc(void) {
360   nghttp2_hd_inflater inflater;
361   nghttp2_bufs bufs;
362   ssize_t blocklen;
363   nghttp2_nv nv[] = {/* Expecting huffman for both */
364                      MAKE_NV("my-long-content-length", "nghttp2"),
365                      /* Expecting no huffman for both */
366                      MAKE_NV("x", "y"),
367                      /* Huffman for key only */
368                      MAKE_NV("my-long-content-length", "y"),
369                      /* Huffman for value only */
370                      MAKE_NV("x", "nghttp2")};
371   size_t i;
372   nva_out out;
373   nghttp2_mem *mem;
374
375   mem = nghttp2_mem_default();
376   frame_pack_bufs_init(&bufs);
377
378   nva_out_init(&out);
379   nghttp2_hd_inflate_init(&inflater, mem);
380   for (i = 0; i < ARRLEN(nv); ++i) {
381     CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&bufs, &nv[i],
382                                                  NGHTTP2_HD_WITHOUT_INDEXING));
383
384     blocklen = nghttp2_bufs_len(&bufs);
385
386     CU_ASSERT(blocklen > 0);
387     CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
388
389     CU_ASSERT(1 == out.nvlen);
390     assert_nv_equal(&nv[i], out.nva, 1, mem);
391     CU_ASSERT(0 == inflater.ctx.hd_table.len);
392
393     nva_out_reset(&out, mem);
394     nghttp2_bufs_reset(&bufs);
395   }
396
397   nghttp2_bufs_free(&bufs);
398   nghttp2_hd_inflate_free(&inflater);
399 }
400
401 void test_nghttp2_hd_inflate_newname_inc(void) {
402   nghttp2_hd_inflater inflater;
403   nghttp2_bufs bufs;
404   ssize_t blocklen;
405   nghttp2_nv nv = MAKE_NV("x-rel", "nghttp2");
406   nva_out out;
407   nghttp2_mem *mem;
408
409   mem = nghttp2_mem_default();
410   frame_pack_bufs_init(&bufs);
411
412   nva_out_init(&out);
413   nghttp2_hd_inflate_init(&inflater, mem);
414
415   CU_ASSERT(
416       0 == nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING));
417
418   blocklen = nghttp2_bufs_len(&bufs);
419
420   CU_ASSERT(blocklen > 0);
421   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
422
423   CU_ASSERT(1 == out.nvlen);
424   assert_nv_equal(&nv, out.nva, 1, mem);
425   CU_ASSERT(1 == inflater.ctx.hd_table.len);
426   assert_nv_equal(
427       &nv, &GET_TABLE_ENT(&inflater.ctx, NGHTTP2_STATIC_TABLE_LENGTH +
428                                              inflater.ctx.hd_table.len - 1)->nv,
429       1, mem);
430
431   nva_out_reset(&out, mem);
432   nghttp2_bufs_free(&bufs);
433   nghttp2_hd_inflate_free(&inflater);
434 }
435
436 void test_nghttp2_hd_inflate_clearall_inc(void) {
437   nghttp2_hd_inflater inflater;
438   nghttp2_bufs bufs;
439   ssize_t blocklen;
440   nghttp2_nv nv;
441   uint8_t value[4061];
442   nva_out out;
443   nghttp2_mem *mem;
444
445   mem = nghttp2_mem_default();
446   bufs_large_init(&bufs, 8192);
447
448   nva_out_init(&out);
449   /* Total 4097 bytes space required to hold this entry */
450   nv.name = (uint8_t *)"alpha";
451   nv.namelen = strlen((char *)nv.name);
452   memset(value, '0', sizeof(value));
453   value[sizeof(value) - 1] = '\0';
454   nv.value = value;
455   nv.valuelen = sizeof(value) - 1;
456
457   nv.flags = NGHTTP2_NV_FLAG_NONE;
458
459   nghttp2_hd_inflate_init(&inflater, mem);
460
461   CU_ASSERT(
462       0 == nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING));
463
464   blocklen = nghttp2_bufs_len(&bufs);
465
466   CU_ASSERT(blocklen > 0);
467   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
468
469   CU_ASSERT(1 == out.nvlen);
470   assert_nv_equal(&nv, out.nva, 1, mem);
471   CU_ASSERT(0 == inflater.ctx.hd_table.len);
472
473   nva_out_reset(&out, mem);
474
475   /* Do it again */
476   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
477
478   CU_ASSERT(1 == out.nvlen);
479   assert_nv_equal(&nv, out.nva, 1, mem);
480   CU_ASSERT(0 == inflater.ctx.hd_table.len);
481
482   nva_out_reset(&out, mem);
483   nghttp2_bufs_reset(&bufs);
484
485   /* This time, 4096 bytes space required, which is just fits in the
486      header table */
487   nv.valuelen = sizeof(value) - 2;
488
489   CU_ASSERT(
490       0 == nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING));
491
492   blocklen = nghttp2_bufs_len(&bufs);
493
494   CU_ASSERT(blocklen > 0);
495   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
496
497   CU_ASSERT(1 == out.nvlen);
498   assert_nv_equal(&nv, out.nva, 1, mem);
499   CU_ASSERT(1 == inflater.ctx.hd_table.len);
500
501   nva_out_reset(&out, mem);
502   nghttp2_bufs_reset(&bufs);
503
504   nghttp2_bufs_free(&bufs);
505   nghttp2_hd_inflate_free(&inflater);
506 }
507
508 void test_nghttp2_hd_inflate_zero_length_huffman(void) {
509   nghttp2_hd_inflater inflater;
510   nghttp2_bufs bufs;
511   /* Literal header without indexing - new name */
512   uint8_t data[] = {0x40, 0x01, 0x78 /* 'x' */, 0x80};
513   nva_out out;
514   nghttp2_mem *mem;
515
516   mem = nghttp2_mem_default();
517   frame_pack_bufs_init(&bufs);
518
519   nva_out_init(&out);
520
521   nghttp2_bufs_add(&bufs, data, sizeof(data));
522
523   /* /\* Literal header without indexing - new name *\/ */
524   /* ptr[0] = 0x40; */
525   /* ptr[1] = 1; */
526   /* ptr[2] = 'x'; */
527   /* ptr[3] = 0x80; */
528
529   nghttp2_hd_inflate_init(&inflater, mem);
530   CU_ASSERT(4 == inflate_hd(&inflater, &out, &bufs, 0, mem));
531
532   CU_ASSERT(1 == out.nvlen);
533   CU_ASSERT(1 == out.nva[0].namelen);
534   CU_ASSERT('x' == out.nva[0].name[0]);
535   CU_ASSERT(NULL == out.nva[0].value);
536   CU_ASSERT(0 == out.nva[0].valuelen);
537
538   nva_out_reset(&out, mem);
539   nghttp2_bufs_free(&bufs);
540   nghttp2_hd_inflate_free(&inflater);
541 }
542
543 void test_nghttp2_hd_ringbuf_reserve(void) {
544   nghttp2_hd_deflater deflater;
545   nghttp2_hd_inflater inflater;
546   nghttp2_nv nv;
547   nghttp2_bufs bufs;
548   nva_out out;
549   int i;
550   ssize_t rv;
551   ssize_t blocklen;
552   nghttp2_mem *mem;
553
554   mem = nghttp2_mem_default();
555   frame_pack_bufs_init(&bufs);
556   nva_out_init(&out);
557
558   nv.flags = NGHTTP2_NV_FLAG_NONE;
559   nv.name = (uint8_t *)"a";
560   nv.namelen = strlen((const char *)nv.name);
561   nv.valuelen = 4;
562   nv.value = mem->malloc(nv.valuelen + 1, NULL);
563   memset(nv.value, 0, nv.valuelen);
564
565   nghttp2_hd_deflate_init2(&deflater, 8000, mem);
566   nghttp2_hd_inflate_init(&inflater, mem);
567
568   nghttp2_hd_inflate_change_table_size(&inflater, 8000);
569   nghttp2_hd_deflate_change_table_size(&deflater, 8000);
570
571   for (i = 0; i < 150; ++i) {
572     memcpy(nv.value, &i, sizeof(i));
573     rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv, 1);
574     blocklen = nghttp2_bufs_len(&bufs);
575
576     CU_ASSERT(0 == rv);
577     CU_ASSERT(blocklen > 0);
578
579     CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
580
581     CU_ASSERT(1 == out.nvlen);
582     assert_nv_equal(&nv, out.nva, 1, mem);
583
584     nva_out_reset(&out, mem);
585     nghttp2_bufs_reset(&bufs);
586   }
587
588   nghttp2_bufs_free(&bufs);
589   nghttp2_hd_inflate_free(&inflater);
590   nghttp2_hd_deflate_free(&deflater);
591
592   mem->free(nv.value, NULL);
593 }
594
595 void test_nghttp2_hd_change_table_size(void) {
596   nghttp2_hd_deflater deflater;
597   nghttp2_hd_inflater inflater;
598   nghttp2_nv nva[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
599   nghttp2_nv nva2[] = {MAKE_NV(":path", "/")};
600   nghttp2_bufs bufs;
601   ssize_t rv;
602   nva_out out;
603   ssize_t blocklen;
604   nghttp2_mem *mem;
605
606   mem = nghttp2_mem_default();
607   frame_pack_bufs_init(&bufs);
608
609   nva_out_init(&out);
610
611   nghttp2_hd_deflate_init(&deflater, mem);
612   nghttp2_hd_inflate_init(&inflater, mem);
613
614   /* inflater changes notifies 8000 max header table size */
615   CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 8000));
616   CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 8000));
617
618   CU_ASSERT(4096 == deflater.ctx.hd_table_bufsize_max);
619
620   CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max);
621   CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
622
623   /* This will emit encoding context update with header table size 4096 */
624   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
625   blocklen = nghttp2_bufs_len(&bufs);
626
627   CU_ASSERT(0 == rv);
628   CU_ASSERT(blocklen > 0);
629   CU_ASSERT(2 == deflater.ctx.hd_table.len);
630   CU_ASSERT(4096 == deflater.ctx.hd_table_bufsize_max);
631
632   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
633   CU_ASSERT(2 == inflater.ctx.hd_table.len);
634   CU_ASSERT(4096 == inflater.ctx.hd_table_bufsize_max);
635   CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
636
637   nva_out_reset(&out, mem);
638   nghttp2_bufs_reset(&bufs);
639
640   /* inflater changes header table size to 1024 */
641   CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 1024));
642   CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 1024));
643
644   CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
645
646   CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max);
647   CU_ASSERT(1024 == inflater.settings_hd_table_bufsize_max);
648
649   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
650   blocklen = nghttp2_bufs_len(&bufs);
651
652   CU_ASSERT(0 == rv);
653   CU_ASSERT(blocklen > 0);
654   CU_ASSERT(2 == deflater.ctx.hd_table.len);
655   CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
656
657   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
658   CU_ASSERT(2 == inflater.ctx.hd_table.len);
659   CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max);
660   CU_ASSERT(1024 == inflater.settings_hd_table_bufsize_max);
661
662   nva_out_reset(&out, mem);
663   nghttp2_bufs_reset(&bufs);
664
665   /* inflater changes header table size to 0 */
666   CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 0));
667   CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 0));
668
669   CU_ASSERT(0 == deflater.ctx.hd_table.len);
670   CU_ASSERT(0 == deflater.ctx.hd_table_bufsize_max);
671
672   CU_ASSERT(0 == inflater.ctx.hd_table.len);
673   CU_ASSERT(0 == inflater.ctx.hd_table_bufsize_max);
674   CU_ASSERT(0 == inflater.settings_hd_table_bufsize_max);
675
676   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
677   blocklen = nghttp2_bufs_len(&bufs);
678
679   CU_ASSERT(0 == rv);
680   CU_ASSERT(blocklen > 0);
681   CU_ASSERT(0 == deflater.ctx.hd_table.len);
682   CU_ASSERT(0 == deflater.ctx.hd_table_bufsize_max);
683
684   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
685   CU_ASSERT(0 == inflater.ctx.hd_table.len);
686   CU_ASSERT(0 == inflater.ctx.hd_table_bufsize_max);
687   CU_ASSERT(0 == inflater.settings_hd_table_bufsize_max);
688
689   nva_out_reset(&out, mem);
690   nghttp2_bufs_reset(&bufs);
691
692   nghttp2_bufs_free(&bufs);
693   nghttp2_hd_inflate_free(&inflater);
694   nghttp2_hd_deflate_free(&deflater);
695
696   /* Check table buffer is expanded */
697   frame_pack_bufs_init(&bufs);
698
699   nghttp2_hd_deflate_init2(&deflater, 8192, mem);
700   nghttp2_hd_inflate_init(&inflater, mem);
701
702   /* First inflater changes header table size to 8000 */
703   CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 8000));
704   CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 8000));
705
706   CU_ASSERT(8000 == deflater.ctx.hd_table_bufsize_max);
707
708   CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max);
709   CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
710
711   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
712   blocklen = nghttp2_bufs_len(&bufs);
713
714   CU_ASSERT(0 == rv);
715   CU_ASSERT(blocklen > 0);
716   CU_ASSERT(2 == deflater.ctx.hd_table.len);
717   CU_ASSERT(8000 == deflater.ctx.hd_table_bufsize_max);
718
719   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
720   CU_ASSERT(2 == inflater.ctx.hd_table.len);
721   CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max);
722   CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
723
724   nva_out_reset(&out, mem);
725   nghttp2_bufs_reset(&bufs);
726
727   CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 16383));
728   CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 16383));
729
730   CU_ASSERT(8192 == deflater.ctx.hd_table_bufsize_max);
731
732   CU_ASSERT(16383 == inflater.ctx.hd_table_bufsize_max);
733   CU_ASSERT(16383 == inflater.settings_hd_table_bufsize_max);
734
735   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
736   blocklen = nghttp2_bufs_len(&bufs);
737
738   CU_ASSERT(0 == rv);
739   CU_ASSERT(blocklen > 0);
740   CU_ASSERT(2 == deflater.ctx.hd_table.len);
741   CU_ASSERT(8192 == deflater.ctx.hd_table_bufsize_max);
742
743   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
744   CU_ASSERT(2 == inflater.ctx.hd_table.len);
745   CU_ASSERT(8192 == inflater.ctx.hd_table_bufsize_max);
746   CU_ASSERT(16383 == inflater.settings_hd_table_bufsize_max);
747
748   nva_out_reset(&out, mem);
749   nghttp2_bufs_reset(&bufs);
750
751   /* Lastly, check the error condition */
752
753   rv = nghttp2_hd_emit_table_size(&bufs, 25600);
754   CU_ASSERT(rv == 0);
755   CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
756             inflate_hd(&inflater, &out, &bufs, 0, mem));
757
758   nva_out_reset(&out, mem);
759   nghttp2_bufs_reset(&bufs);
760
761   nghttp2_hd_inflate_free(&inflater);
762   nghttp2_hd_deflate_free(&deflater);
763
764   /* Check that encoder can handle the case where its allowable buffer
765      size is less than default size, 4096 */
766   nghttp2_hd_deflate_init2(&deflater, 1024, mem);
767   nghttp2_hd_inflate_init(&inflater, mem);
768
769   CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
770
771   /* This emits context update with buffer size 1024 */
772   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
773   blocklen = nghttp2_bufs_len(&bufs);
774
775   CU_ASSERT(0 == rv);
776   CU_ASSERT(blocklen > 0);
777   CU_ASSERT(2 == deflater.ctx.hd_table.len);
778   CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
779
780   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
781   CU_ASSERT(2 == inflater.ctx.hd_table.len);
782   CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max);
783   CU_ASSERT(4096 == inflater.settings_hd_table_bufsize_max);
784
785   nva_out_reset(&out, mem);
786   nghttp2_bufs_reset(&bufs);
787
788   nghttp2_hd_inflate_free(&inflater);
789   nghttp2_hd_deflate_free(&deflater);
790
791   /* Check that table size UINT32_MAX can be received */
792   nghttp2_hd_deflate_init2(&deflater, UINT32_MAX, mem);
793   nghttp2_hd_inflate_init(&inflater, mem);
794
795   CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, UINT32_MAX));
796   CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, UINT32_MAX));
797
798   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
799   blocklen = nghttp2_bufs_len(&bufs);
800
801   CU_ASSERT(0 == rv);
802   CU_ASSERT(UINT32_MAX == deflater.ctx.hd_table_bufsize_max);
803
804   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
805   CU_ASSERT(UINT32_MAX == inflater.ctx.hd_table_bufsize_max);
806   CU_ASSERT(UINT32_MAX == inflater.settings_hd_table_bufsize_max);
807
808   nva_out_reset(&out, mem);
809   nghttp2_bufs_reset(&bufs);
810
811   nghttp2_hd_inflate_free(&inflater);
812   nghttp2_hd_deflate_free(&deflater);
813
814   /* Check that context update emitted twice */
815   nghttp2_hd_deflate_init2(&deflater, 4096, mem);
816   nghttp2_hd_inflate_init(&inflater, mem);
817
818   CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 0));
819   CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 3000));
820   CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 0));
821   CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 3000));
822
823   CU_ASSERT(0 == deflater.min_hd_table_bufsize_max);
824   CU_ASSERT(3000 == deflater.ctx.hd_table_bufsize_max);
825
826   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, 1);
827   blocklen = nghttp2_bufs_len(&bufs);
828
829   CU_ASSERT(0 == rv);
830   CU_ASSERT(3 < blocklen);
831   CU_ASSERT(3000 == deflater.ctx.hd_table_bufsize_max);
832   CU_ASSERT(UINT32_MAX == deflater.min_hd_table_bufsize_max);
833
834   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
835   CU_ASSERT(3000 == inflater.ctx.hd_table_bufsize_max);
836   CU_ASSERT(3000 == inflater.settings_hd_table_bufsize_max);
837
838   nva_out_reset(&out, mem);
839   nghttp2_bufs_reset(&bufs);
840
841   nghttp2_hd_inflate_free(&inflater);
842   nghttp2_hd_deflate_free(&deflater);
843
844   nghttp2_bufs_free(&bufs);
845 }
846
847 static void check_deflate_inflate(nghttp2_hd_deflater *deflater,
848                                   nghttp2_hd_inflater *inflater,
849                                   nghttp2_nv *nva, size_t nvlen,
850                                   nghttp2_mem *mem) {
851   nghttp2_bufs bufs;
852   ssize_t blocklen;
853   nva_out out;
854   int rv;
855
856   frame_pack_bufs_init(&bufs);
857
858   nva_out_init(&out);
859   rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nva, nvlen);
860   blocklen = nghttp2_bufs_len(&bufs);
861
862   CU_ASSERT(0 == rv);
863   CU_ASSERT(blocklen >= 0);
864
865   CU_ASSERT(blocklen == inflate_hd(inflater, &out, &bufs, 0, mem));
866
867   CU_ASSERT(nvlen == out.nvlen);
868   assert_nv_equal(nva, out.nva, nvlen, mem);
869
870   nva_out_reset(&out, mem);
871   nghttp2_bufs_free(&bufs);
872 }
873
874 void test_nghttp2_hd_deflate_inflate(void) {
875   nghttp2_hd_deflater deflater;
876   nghttp2_hd_inflater inflater;
877   nghttp2_nv nv1[] = {
878       MAKE_NV(":status", "200 OK"),
879       MAKE_NV("access-control-allow-origin", "*"),
880       MAKE_NV("cache-control", "private, max-age=0, must-revalidate"),
881       MAKE_NV("content-length", "76073"),
882       MAKE_NV("content-type", "text/html"),
883       MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
884       MAKE_NV("expires", "Sat, 27 Jul 2013 06:22:12 GMT"),
885       MAKE_NV("server", "Apache"),
886       MAKE_NV("vary", "foobar"),
887       MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
888       MAKE_NV("x-cache", "MISS from alphabravo"),
889       MAKE_NV("x-cache-action", "MISS"),
890       MAKE_NV("x-cache-age", "0"),
891       MAKE_NV("x-cache-lookup", "MISS from alphabravo:3128"),
892       MAKE_NV("x-lb-nocache", "true"),
893   };
894   nghttp2_nv nv2[] = {
895       MAKE_NV(":status", "304 Not Modified"),
896       MAKE_NV("age", "0"),
897       MAKE_NV("cache-control", "max-age=56682045"),
898       MAKE_NV("content-type", "text/css"),
899       MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
900       MAKE_NV("expires", "Thu, 14 May 2015 07:22:57 GMT"),
901       MAKE_NV("last-modified", "Tue, 14 May 2013 07:22:15 GMT"),
902       MAKE_NV("vary", "Accept-Encoding"),
903       MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
904       MAKE_NV("x-cache", "HIT from alphabravo"),
905       MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128")};
906   nghttp2_nv nv3[] = {
907       MAKE_NV(":status", "304 Not Modified"),
908       MAKE_NV("age", "0"),
909       MAKE_NV("cache-control", "max-age=56682072"),
910       MAKE_NV("content-type", "text/css"),
911       MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
912       MAKE_NV("expires", "Thu, 14 May 2015 07:23:24 GMT"),
913       MAKE_NV("last-modified", "Tue, 14 May 2013 07:22:13 GMT"),
914       MAKE_NV("vary", "Accept-Encoding"),
915       MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
916       MAKE_NV("x-cache", "HIT from alphabravo"),
917       MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
918   };
919   nghttp2_nv nv4[] = {
920       MAKE_NV(":status", "304 Not Modified"),
921       MAKE_NV("age", "0"),
922       MAKE_NV("cache-control", "max-age=56682022"),
923       MAKE_NV("content-type", "text/css"),
924       MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
925       MAKE_NV("expires", "Thu, 14 May 2015 07:22:34 GMT"),
926       MAKE_NV("last-modified", "Tue, 14 May 2013 07:22:14 GMT"),
927       MAKE_NV("vary", "Accept-Encoding"),
928       MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
929       MAKE_NV("x-cache", "HIT from alphabravo"),
930       MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
931   };
932   nghttp2_nv nv5[] = {
933       MAKE_NV(":status", "304 Not Modified"),
934       MAKE_NV("age", "0"),
935       MAKE_NV("cache-control", "max-age=4461139"),
936       MAKE_NV("content-type", "application/x-javascript"),
937       MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
938       MAKE_NV("expires", "Mon, 16 Sep 2013 21:34:31 GMT"),
939       MAKE_NV("last-modified", "Thu, 05 May 2011 09:15:59 GMT"),
940       MAKE_NV("vary", "Accept-Encoding"),
941       MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
942       MAKE_NV("x-cache", "HIT from alphabravo"),
943       MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
944   };
945   nghttp2_nv nv6[] = {
946       MAKE_NV(":status", "304 Not Modified"),
947       MAKE_NV("age", "0"),
948       MAKE_NV("cache-control", "max-age=18645951"),
949       MAKE_NV("content-type", "application/x-javascript"),
950       MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
951       MAKE_NV("expires", "Fri, 28 Feb 2014 01:48:03 GMT"),
952       MAKE_NV("last-modified", "Tue, 12 Jul 2011 16:02:59 GMT"),
953       MAKE_NV("vary", "Accept-Encoding"),
954       MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
955       MAKE_NV("x-cache", "HIT from alphabravo"),
956       MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
957   };
958   nghttp2_nv nv7[] = {
959       MAKE_NV(":status", "304 Not Modified"),
960       MAKE_NV("age", "0"),
961       MAKE_NV("cache-control", "max-age=31536000"),
962       MAKE_NV("content-type", "application/javascript"),
963       MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
964       MAKE_NV("etag", "\"6807-4dc5b54e0dcc0\""),
965       MAKE_NV("expires", "Wed, 21 May 2014 08:32:17 GMT"),
966       MAKE_NV("last-modified", "Fri, 10 May 2013 11:18:51 GMT"),
967       MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
968       MAKE_NV("x-cache", "HIT from alphabravo"),
969       MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
970   };
971   nghttp2_nv nv8[] = {
972       MAKE_NV(":status", "304 Not Modified"),
973       MAKE_NV("age", "0"),
974       MAKE_NV("cache-control", "max-age=31536000"),
975       MAKE_NV("content-type", "application/javascript"),
976       MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
977       MAKE_NV("etag", "\"41c6-4de7d28585b00\""),
978       MAKE_NV("expires", "Thu, 12 Jun 2014 10:00:58 GMT"),
979       MAKE_NV("last-modified", "Thu, 06 Jun 2013 14:30:36 GMT"),
980       MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
981       MAKE_NV("x-cache", "HIT from alphabravo"),
982       MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
983   };
984   nghttp2_nv nv9[] = {
985       MAKE_NV(":status", "304 Not Modified"),
986       MAKE_NV("age", "0"),
987       MAKE_NV("cache-control", "max-age=31536000"),
988       MAKE_NV("content-type", "application/javascript"),
989       MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
990       MAKE_NV("etag", "\"19d6e-4dc5b35a541c0\""),
991       MAKE_NV("expires", "Wed, 21 May 2014 08:32:18 GMT"),
992       MAKE_NV("last-modified", "Fri, 10 May 2013 11:10:07 GMT"),
993       MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
994       MAKE_NV("x-cache", "HIT from alphabravo"),
995       MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
996   };
997   nghttp2_nv nv10[] = {
998       MAKE_NV(":status", "304 Not Modified"),
999       MAKE_NV("age", "0"),
1000       MAKE_NV("cache-control", "max-age=56682045"),
1001       MAKE_NV("content-type", "text/css"),
1002       MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1003       MAKE_NV("expires", "Thu, 14 May 2015 07:22:57 GMT"),
1004       MAKE_NV("last-modified", "Tue, 14 May 2013 07:21:53 GMT"),
1005       MAKE_NV("vary", "Accept-Encoding"),
1006       MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1007       MAKE_NV("x-cache", "HIT from alphabravo"),
1008       MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1009   };
1010   nghttp2_mem *mem;
1011
1012   mem = nghttp2_mem_default();
1013
1014   nghttp2_hd_deflate_init(&deflater, mem);
1015   nghttp2_hd_inflate_init(&inflater, mem);
1016
1017   check_deflate_inflate(&deflater, &inflater, nv1, ARRLEN(nv1), mem);
1018   check_deflate_inflate(&deflater, &inflater, nv2, ARRLEN(nv2), mem);
1019   check_deflate_inflate(&deflater, &inflater, nv3, ARRLEN(nv3), mem);
1020   check_deflate_inflate(&deflater, &inflater, nv4, ARRLEN(nv4), mem);
1021   check_deflate_inflate(&deflater, &inflater, nv5, ARRLEN(nv5), mem);
1022   check_deflate_inflate(&deflater, &inflater, nv6, ARRLEN(nv6), mem);
1023   check_deflate_inflate(&deflater, &inflater, nv7, ARRLEN(nv7), mem);
1024   check_deflate_inflate(&deflater, &inflater, nv8, ARRLEN(nv8), mem);
1025   check_deflate_inflate(&deflater, &inflater, nv9, ARRLEN(nv9), mem);
1026   check_deflate_inflate(&deflater, &inflater, nv10, ARRLEN(nv10), mem);
1027
1028   nghttp2_hd_inflate_free(&inflater);
1029   nghttp2_hd_deflate_free(&deflater);
1030 }
1031
1032 void test_nghttp2_hd_no_index(void) {
1033   nghttp2_hd_deflater deflater;
1034   nghttp2_hd_inflater inflater;
1035   nghttp2_bufs bufs;
1036   ssize_t blocklen;
1037   nghttp2_nv nva[] = {
1038       MAKE_NV(":method", "GET"), MAKE_NV(":method", "POST"),
1039       MAKE_NV(":path", "/foo"),  MAKE_NV("version", "HTTP/1.1"),
1040       MAKE_NV(":method", "GET"),
1041   };
1042   size_t i;
1043   nva_out out;
1044   int rv;
1045   nghttp2_mem *mem;
1046
1047   mem = nghttp2_mem_default();
1048
1049   /* 1st :method: GET can be indexable, last one is not */
1050   for (i = 1; i < ARRLEN(nva); ++i) {
1051     nva[i].flags = NGHTTP2_NV_FLAG_NO_INDEX;
1052   }
1053
1054   frame_pack_bufs_init(&bufs);
1055
1056   nva_out_init(&out);
1057
1058   nghttp2_hd_deflate_init(&deflater, mem);
1059   nghttp2_hd_inflate_init(&inflater, mem);
1060
1061   rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, ARRLEN(nva));
1062   blocklen = nghttp2_bufs_len(&bufs);
1063
1064   CU_ASSERT(0 == rv);
1065   CU_ASSERT(blocklen > 0);
1066   CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem));
1067
1068   CU_ASSERT(ARRLEN(nva) == out.nvlen);
1069   assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1070
1071   CU_ASSERT(out.nva[0].flags == NGHTTP2_NV_FLAG_NONE);
1072   for (i = 1; i < ARRLEN(nva); ++i) {
1073     CU_ASSERT(out.nva[i].flags == NGHTTP2_NV_FLAG_NO_INDEX);
1074   }
1075
1076   nva_out_reset(&out, mem);
1077
1078   nghttp2_bufs_free(&bufs);
1079   nghttp2_hd_inflate_free(&inflater);
1080   nghttp2_hd_deflate_free(&deflater);
1081 }
1082
1083 void test_nghttp2_hd_deflate_bound(void) {
1084   nghttp2_hd_deflater deflater;
1085   nghttp2_nv nva[] = {MAKE_NV(":method", "GET"), MAKE_NV("alpha", "bravo")};
1086   nghttp2_bufs bufs;
1087   size_t bound, bound2;
1088   nghttp2_mem *mem;
1089
1090   mem = nghttp2_mem_default();
1091   frame_pack_bufs_init(&bufs);
1092
1093   nghttp2_hd_deflate_init(&deflater, mem);
1094
1095   bound = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva));
1096
1097   CU_ASSERT(12 + 6 * 2 * 2 + nva[0].namelen + nva[0].valuelen + nva[1].namelen +
1098                 nva[1].valuelen ==
1099             bound);
1100
1101   nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, ARRLEN(nva));
1102
1103   CU_ASSERT(bound > (size_t)nghttp2_bufs_len(&bufs));
1104
1105   bound2 = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva));
1106
1107   CU_ASSERT(bound == bound2);
1108
1109   nghttp2_bufs_free(&bufs);
1110   nghttp2_hd_deflate_free(&deflater);
1111 }
1112
1113 void test_nghttp2_hd_public_api(void) {
1114   nghttp2_hd_deflater *deflater;
1115   nghttp2_hd_inflater *inflater;
1116   nghttp2_nv nva[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
1117   uint8_t buf[4096];
1118   size_t buflen;
1119   ssize_t blocklen;
1120   nghttp2_bufs bufs;
1121   nghttp2_mem *mem;
1122
1123   mem = nghttp2_mem_default();
1124
1125   CU_ASSERT(0 == nghttp2_hd_deflate_new(&deflater, 4096));
1126   CU_ASSERT(0 == nghttp2_hd_inflate_new(&inflater));
1127
1128   buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1129
1130   blocklen = nghttp2_hd_deflate_hd(deflater, buf, buflen, nva, ARRLEN(nva));
1131
1132   CU_ASSERT(blocklen > 0);
1133
1134   nghttp2_bufs_wrap_init(&bufs, buf, blocklen, mem);
1135   bufs.head->buf.last += blocklen;
1136
1137   CU_ASSERT(blocklen == inflate_hd(inflater, NULL, &bufs, 0, mem));
1138
1139   nghttp2_bufs_wrap_free(&bufs);
1140
1141   nghttp2_hd_inflate_del(inflater);
1142   nghttp2_hd_deflate_del(deflater);
1143
1144   /* See NGHTTP2_ERR_INSUFF_BUFSIZE */
1145   CU_ASSERT(0 == nghttp2_hd_deflate_new(&deflater, 4096));
1146
1147   blocklen =
1148       nghttp2_hd_deflate_hd(deflater, buf, blocklen - 1, nva, ARRLEN(nva));
1149
1150   CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == blocklen);
1151
1152   nghttp2_hd_deflate_del(deflater);
1153 }
1154
1155 static size_t encode_length(uint8_t *buf, uint64_t n, size_t prefix) {
1156   size_t k = (1 << prefix) - 1;
1157   size_t len = 0;
1158   *buf &= ~k;
1159   if (n >= k) {
1160     *buf++ |= k;
1161     n -= k;
1162     ++len;
1163   } else {
1164     *buf++ |= n;
1165     return 1;
1166   }
1167   do {
1168     ++len;
1169     if (n >= 128) {
1170       *buf++ = (1 << 7) | (n & 0x7f);
1171       n >>= 7;
1172     } else {
1173       *buf++ = (uint8_t)n;
1174       break;
1175     }
1176   } while (n);
1177   return len;
1178 }
1179
1180 void test_nghttp2_hd_decode_length(void) {
1181   uint32_t out;
1182   size_t shift;
1183   int final;
1184   uint8_t buf[16];
1185   uint8_t *bufp;
1186   size_t len;
1187   ssize_t rv;
1188   size_t i;
1189
1190   memset(buf, 0, sizeof(buf));
1191   len = encode_length(buf, UINT32_MAX, 7);
1192
1193   rv = nghttp2_hd_decode_length(&out, &shift, &final, 0, 0, buf, buf + len, 7);
1194
1195   CU_ASSERT((ssize_t)len == rv);
1196   CU_ASSERT(0 != final);
1197   CU_ASSERT(UINT32_MAX == out);
1198
1199   /* Make sure that we can decode integer if we feed 1 byte at a
1200      time */
1201   out = 0;
1202   shift = 0;
1203   final = 0;
1204   bufp = buf;
1205
1206   for (i = 0; i < len; ++i, ++bufp) {
1207     rv = nghttp2_hd_decode_length(&out, &shift, &final, out, shift, bufp,
1208                                   bufp + 1, 7);
1209
1210     CU_ASSERT(rv == 1);
1211
1212     if (final) {
1213       break;
1214     }
1215   }
1216
1217   CU_ASSERT(i == len - 1);
1218   CU_ASSERT(0 != final);
1219   CU_ASSERT(UINT32_MAX == out);
1220
1221   /* Check overflow case */
1222   memset(buf, 0, sizeof(buf));
1223   len = encode_length(buf, 1ll << 32, 7);
1224
1225   rv = nghttp2_hd_decode_length(&out, &shift, &final, 0, 0, buf, buf + len, 7);
1226
1227   CU_ASSERT(-1 == rv);
1228 }
1229
1230 void test_nghttp2_hd_huff_encode(void) {
1231   int rv;
1232   ssize_t len;
1233   nghttp2_bufs bufs, outbufs;
1234   nghttp2_hd_huff_decode_context ctx;
1235   const uint8_t t1[] = {22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
1236                         10, 9,  8,  7,  6,  5,  4,  3,  2,  1,  0};
1237
1238   frame_pack_bufs_init(&bufs);
1239   frame_pack_bufs_init(&outbufs);
1240
1241   rv = nghttp2_hd_huff_encode(&bufs, t1, sizeof(t1));
1242
1243   CU_ASSERT(rv == 0);
1244
1245   nghttp2_hd_huff_decode_context_init(&ctx);
1246
1247   len = nghttp2_hd_huff_decode(&ctx, &outbufs, bufs.cur->buf.pos,
1248                                nghttp2_bufs_len(&bufs), 1);
1249
1250   CU_ASSERT(nghttp2_bufs_len(&bufs) == len);
1251   CU_ASSERT((ssize_t)sizeof(t1) == nghttp2_bufs_len(&outbufs));
1252
1253   CU_ASSERT(0 == memcmp(t1, outbufs.cur->buf.pos, sizeof(t1)));
1254
1255   nghttp2_bufs_free(&bufs);
1256   nghttp2_bufs_free(&outbufs);
1257 }