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