blob: bda8298eb3803234093588d23ce6f0bb621c1981 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller06059952015-02-18 08:34:56 -08003 * Copyright 2015, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include "src/core/transport/chttp2/stream_encoder.h"
35
36#include <stdio.h>
37
Craig Tiller485d7762015-01-23 12:54:05 -080038#include "src/core/support/string.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080039#include "src/core/transport/chttp2/hpack_parser.h"
40#include <grpc/support/alloc.h>
41#include <grpc/support/log.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080042#include "test/core/util/parse_hexstring.h"
43#include "test/core/util/slice_splitter.h"
44#include "test/core/util/test_config.h"
45
46#define TEST(x) run_test(x, #x)
47
48grpc_mdctx *g_mdctx;
49grpc_chttp2_hpack_compressor g_compressor;
50int g_failure = 0;
51grpc_stream_op_buffer g_sopb;
52
Craig Tillerbd222712015-04-17 16:09:40 -070053void **to_delete = NULL;
54int num_to_delete = 0;
55int cap_to_delete = 0;
56
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080057static gpr_slice create_test_slice(size_t length) {
58 gpr_slice slice = gpr_slice_malloc(length);
59 size_t i;
60 for (i = 0; i < length; i++) {
61 GPR_SLICE_START_PTR(slice)[i] = i;
62 }
63 return slice;
64}
65
66/* verify that the output generated by encoding the stream matches the
67 hexstring passed in */
68static void verify_sopb(size_t window_available, int eof,
69 size_t expect_window_used, const char *expected) {
70 gpr_slice_buffer output;
ctiller00297df2015-01-12 11:23:09 -080071 grpc_stream_op_buffer encops;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080072 gpr_slice merged;
73 gpr_slice expect = parse_hexstring(expected);
74 gpr_slice_buffer_init(&output);
ctiller00297df2015-01-12 11:23:09 -080075 grpc_sopb_init(&encops);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080076 GPR_ASSERT(expect_window_used ==
ctiller00297df2015-01-12 11:23:09 -080077 grpc_chttp2_preencode(g_sopb.ops, &g_sopb.nops, window_available,
78 &encops));
79 grpc_chttp2_encode(encops.ops, encops.nops, eof, 0xdeadbeef, &g_compressor,
80 &output);
81 encops.nops = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080082 merged = grpc_slice_merge(output.slices, output.count);
83 gpr_slice_buffer_destroy(&output);
ctiller00297df2015-01-12 11:23:09 -080084 grpc_sopb_destroy(&encops);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080085
86 if (0 != gpr_slice_cmp(merged, expect)) {
87 char *expect_str =
88 gpr_hexdump((char *)GPR_SLICE_START_PTR(expect),
89 GPR_SLICE_LENGTH(expect), GPR_HEXDUMP_PLAINTEXT);
90 char *got_str =
91 gpr_hexdump((char *)GPR_SLICE_START_PTR(merged),
92 GPR_SLICE_LENGTH(merged), GPR_HEXDUMP_PLAINTEXT);
93 gpr_log(GPR_ERROR, "mismatched output for %s", expected);
94 gpr_log(GPR_ERROR, "EXPECT: %s", expect_str);
95 gpr_log(GPR_ERROR, "GOT: %s", got_str);
96 gpr_free(expect_str);
97 gpr_free(got_str);
98 g_failure = 1;
99 }
100
101 gpr_slice_unref(merged);
102 gpr_slice_unref(expect);
103}
104
105static void assert_result_ok(void *user_data, grpc_op_error error) {
106 GPR_ASSERT(error == GRPC_OP_OK);
107}
108
Craig Tiller32946d32015-01-15 11:37:30 -0800109static void test_small_data_framing(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800110 grpc_sopb_add_no_op(&g_sopb);
111 verify_sopb(10, 0, 0, "");
112
113 grpc_sopb_add_flow_ctl_cb(&g_sopb, assert_result_ok, NULL);
114 grpc_sopb_add_slice(&g_sopb, create_test_slice(3));
115 verify_sopb(10, 0, 3, "000003 0000 deadbeef 000102");
116
117 grpc_sopb_add_slice(&g_sopb, create_test_slice(4));
118 verify_sopb(10, 0, 4, "000004 0000 deadbeef 00010203");
119
120 grpc_sopb_add_slice(&g_sopb, create_test_slice(3));
121 grpc_sopb_add_slice(&g_sopb, create_test_slice(4));
122 verify_sopb(10, 0, 7, "000007 0000 deadbeef 000102 00010203");
123
124 grpc_sopb_add_slice(&g_sopb, create_test_slice(0));
125 grpc_sopb_add_slice(&g_sopb, create_test_slice(0));
126 grpc_sopb_add_slice(&g_sopb, create_test_slice(0));
127 grpc_sopb_add_slice(&g_sopb, create_test_slice(0));
128 grpc_sopb_add_slice(&g_sopb, create_test_slice(3));
129 verify_sopb(10, 0, 3, "000003 0000 deadbeef 000102");
130
131 verify_sopb(10, 1, 0, "000000 0001 deadbeef");
132
133 grpc_sopb_add_begin_message(&g_sopb, 255, 0);
134 verify_sopb(10, 0, 5, "000005 0000 deadbeef 00000000ff");
135}
136
Craig Tiller9c1043e2015-04-16 16:20:38 -0700137static void add_sopb_headers(int n, ...) {
138 int i;
139 grpc_metadata_batch b;
140 va_list l;
141 grpc_linked_mdelem *e = gpr_malloc(sizeof(*e) * n);
142
Craig Tillerbd222712015-04-17 16:09:40 -0700143 grpc_metadata_batch_init(&b);
144
Craig Tiller9c1043e2015-04-16 16:20:38 -0700145 va_start(l, n);
146 for (i = 0; i < n; i++) {
147 char *key = va_arg(l, char *);
148 char *value = va_arg(l, char *);
149 if (i) {
Craig Tiller5c019ae2015-04-17 16:46:53 -0700150 e[i - 1].next = &e[i];
151 e[i].prev = &e[i - 1];
Craig Tiller9c1043e2015-04-16 16:20:38 -0700152 }
153 e[i].md = grpc_mdelem_from_strings(g_mdctx, key, value);
154 }
155 e[0].prev = NULL;
Craig Tiller5c019ae2015-04-17 16:46:53 -0700156 e[n - 1].next = NULL;
Craig Tiller9c1043e2015-04-16 16:20:38 -0700157 va_end(l);
158
Craig Tillerbd222712015-04-17 16:09:40 -0700159 b.list.head = &e[0];
Craig Tiller5c019ae2015-04-17 16:46:53 -0700160 b.list.tail = &e[n - 1];
Craig Tillerbd222712015-04-17 16:09:40 -0700161
162 if (cap_to_delete == num_to_delete) {
Craig Tiller5c019ae2015-04-17 16:46:53 -0700163 cap_to_delete = GPR_MAX(2 * cap_to_delete, 1000);
Craig Tillerbd222712015-04-17 16:09:40 -0700164 to_delete = gpr_realloc(to_delete, sizeof(*to_delete) * cap_to_delete);
165 }
166 to_delete[num_to_delete++] = e;
167
Craig Tiller9c1043e2015-04-16 16:20:38 -0700168 grpc_sopb_add_metadata(&g_sopb, b);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800169}
170
Craig Tiller32946d32015-01-15 11:37:30 -0800171static void test_basic_headers(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800172 int i;
173
Craig Tiller9c1043e2015-04-16 16:20:38 -0700174 add_sopb_headers(1, "a", "a");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800175 verify_sopb(0, 0, 0, "000005 0104 deadbeef 40 0161 0161");
176
Craig Tiller9c1043e2015-04-16 16:20:38 -0700177 add_sopb_headers(1, "a", "a");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800178 verify_sopb(0, 0, 0, "000001 0104 deadbeef be");
179
Craig Tiller9c1043e2015-04-16 16:20:38 -0700180 add_sopb_headers(1, "a", "a");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800181 verify_sopb(0, 0, 0, "000001 0104 deadbeef be");
182
Craig Tiller9c1043e2015-04-16 16:20:38 -0700183 add_sopb_headers(2, "a", "a", "b", "c");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800184 verify_sopb(0, 0, 0, "000006 0104 deadbeef be 40 0162 0163");
185
Craig Tiller9c1043e2015-04-16 16:20:38 -0700186 add_sopb_headers(2, "a", "a", "b", "c");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800187 verify_sopb(0, 0, 0, "000002 0104 deadbeef bf be");
188
Craig Tiller9c1043e2015-04-16 16:20:38 -0700189 add_sopb_headers(1, "a", "d");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800190 verify_sopb(0, 0, 0, "000004 0104 deadbeef 7f 00 0164");
191
192 /* flush out what's there to make a few values look very popular */
193 for (i = 0; i < 350; i++) {
Craig Tiller9c1043e2015-04-16 16:20:38 -0700194 add_sopb_headers(3, "a", "a", "b", "c", "a", "d");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800195 verify_sopb(0, 0, 0, "000003 0104 deadbeef c0 bf be");
196 }
197
Craig Tiller9c1043e2015-04-16 16:20:38 -0700198 add_sopb_headers(2, "a", "a", "k", "v");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800199 verify_sopb(0, 0, 0, "000006 0104 deadbeef c0 00 016b 0176");
200
Craig Tiller9c1043e2015-04-16 16:20:38 -0700201 add_sopb_headers(1, "a", "v");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800202 /* this could be 000004 0104 deadbeef 0f 30 0176 also */
203 verify_sopb(0, 0, 0, "000004 0104 deadbeef 0f 2f 0176");
204}
205
206static void encode_int_to_str(int i, char *p) {
207 p[0] = 'a' + i % 26;
208 i /= 26;
209 GPR_ASSERT(i < 26);
210 p[1] = 'a' + i;
211 p[2] = 0;
212}
213
Craig Tiller32946d32015-01-15 11:37:30 -0800214static void test_decode_table_overflow(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800215 int i;
216 char key[3], value[3];
Craig Tiller28214ea2015-01-23 15:17:07 -0800217 char *expect;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800218
219 for (i = 0; i < 114; i++) {
220 if (i > 0) {
Craig Tiller9c1043e2015-04-16 16:20:38 -0700221 add_sopb_headers(1, "aa", "ba");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800222 }
223
224 encode_int_to_str(i, key);
225 encode_int_to_str(i + 1, value);
226
227 if (i + 61 >= 127) {
Craig Tiller28214ea2015-01-23 15:17:07 -0800228 gpr_asprintf(&expect,
Craig Tiller5c019ae2015-04-17 16:46:53 -0700229 "000002 0104 deadbeef ff%02x 000007 0104 deadbeef 40 "
230 "02%02x%02x 02%02x%02x",
Craig Tiller28214ea2015-01-23 15:17:07 -0800231 i + 61 - 127, key[0], key[1], value[0], value[1]);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800232 } else if (i > 0) {
Craig Tiller28214ea2015-01-23 15:17:07 -0800233 gpr_asprintf(&expect,
Craig Tiller5c019ae2015-04-17 16:46:53 -0700234 "000001 0104 deadbeef %02x 000007 0104 deadbeef 40 "
235 "02%02x%02x 02%02x%02x",
Craig Tiller28214ea2015-01-23 15:17:07 -0800236 0x80 + 61 + i, key[0], key[1], value[0], value[1]);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800237 } else {
Craig Tiller28214ea2015-01-23 15:17:07 -0800238 gpr_asprintf(&expect, "000007 0104 deadbeef 40 02%02x%02x 02%02x%02x",
239 key[0], key[1], value[0], value[1]);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800240 }
241
Craig Tiller9c1043e2015-04-16 16:20:38 -0700242 add_sopb_headers(1, key, value);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800243 verify_sopb(0, 0, 0, expect);
Craig Tiller28214ea2015-01-23 15:17:07 -0800244 gpr_free(expect);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800245 }
246
247 /* if the above passes, then we must have just knocked this pair out of the
248 decoder stack, and so we'll be forced to re-encode it */
Craig Tiller9c1043e2015-04-16 16:20:38 -0700249 add_sopb_headers(1, "aa", "ba");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800250 verify_sopb(0, 0, 0, "000007 0104 deadbeef 40 026161 026261");
251}
252
253static void randstr(char *p, int bufsz) {
254 int i;
255 int len = 1 + rand() % bufsz;
256 for (i = 0; i < len; i++) {
257 p[i] = 'a' + rand() % 26;
258 }
259 p[len] = 0;
260}
261
262typedef struct {
263 char key[300];
264 char value[300];
265 int got_hdr;
266} test_decode_random_header_state;
267
268static void chk_hdr(void *p, grpc_mdelem *el) {
269 test_decode_random_header_state *st = p;
270 GPR_ASSERT(0 == gpr_slice_str_cmp(el->key->slice, st->key));
271 GPR_ASSERT(0 == gpr_slice_str_cmp(el->value->slice, st->value));
272 st->got_hdr = 1;
273 grpc_mdelem_unref(el);
274}
275
276static void test_decode_random_headers_inner(int max_len) {
277 int i;
278 test_decode_random_header_state st;
279 gpr_slice_buffer output;
280 gpr_slice merged;
ctiller00297df2015-01-12 11:23:09 -0800281 grpc_stream_op_buffer encops;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800282 grpc_chttp2_hpack_parser parser;
283
284 grpc_chttp2_hpack_parser_init(&parser, g_mdctx);
ctiller00297df2015-01-12 11:23:09 -0800285 grpc_sopb_init(&encops);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800286
287 gpr_log(GPR_INFO, "max_len = %d", max_len);
288
ctiller00297df2015-01-12 11:23:09 -0800289 for (i = 0; i < 10000; i++) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800290 randstr(st.key, max_len);
291 randstr(st.value, max_len);
292
Craig Tiller9c1043e2015-04-16 16:20:38 -0700293 add_sopb_headers(1, st.key, st.value);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800294 gpr_slice_buffer_init(&output);
ctiller00297df2015-01-12 11:23:09 -0800295 GPR_ASSERT(0 ==
296 grpc_chttp2_preencode(g_sopb.ops, &g_sopb.nops, 0, &encops));
297 grpc_chttp2_encode(encops.ops, encops.nops, 0, 0xdeadbeef, &g_compressor,
298 &output);
299 encops.nops = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800300 merged = grpc_slice_merge(output.slices, output.count);
301 gpr_slice_buffer_destroy(&output);
302
303 st.got_hdr = 0;
304 parser.on_header = chk_hdr;
305 parser.on_header_user_data = &st;
306 grpc_chttp2_hpack_parser_parse(&parser, GPR_SLICE_START_PTR(merged) + 9,
307 GPR_SLICE_END_PTR(merged));
308 GPR_ASSERT(st.got_hdr);
309
310 gpr_slice_unref(merged);
311 }
312
313 grpc_chttp2_hpack_parser_destroy(&parser);
ctiller00297df2015-01-12 11:23:09 -0800314 grpc_sopb_destroy(&encops);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800315}
316
Craig Tiller3eef2c42015-01-15 11:37:54 -0800317#define DECL_TEST_DECODE_RANDOM_HEADERS(n) \
Craig Tiller32946d32015-01-15 11:37:30 -0800318 static void test_decode_random_headers_##n(void) { \
Craig Tiller3eef2c42015-01-15 11:37:54 -0800319 test_decode_random_headers_inner(n); \
320 } \
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800321 int keeps_formatting_correct_##n
322
323DECL_TEST_DECODE_RANDOM_HEADERS(1);
324DECL_TEST_DECODE_RANDOM_HEADERS(2);
325DECL_TEST_DECODE_RANDOM_HEADERS(3);
326DECL_TEST_DECODE_RANDOM_HEADERS(5);
327DECL_TEST_DECODE_RANDOM_HEADERS(8);
328DECL_TEST_DECODE_RANDOM_HEADERS(13);
329DECL_TEST_DECODE_RANDOM_HEADERS(21);
330DECL_TEST_DECODE_RANDOM_HEADERS(34);
331DECL_TEST_DECODE_RANDOM_HEADERS(55);
332DECL_TEST_DECODE_RANDOM_HEADERS(89);
333DECL_TEST_DECODE_RANDOM_HEADERS(144);
334
335static void run_test(void (*test)(), const char *name) {
336 gpr_log(GPR_INFO, "RUN TEST: %s", name);
337 g_mdctx = grpc_mdctx_create_with_seed(0);
338 grpc_chttp2_hpack_compressor_init(&g_compressor, g_mdctx);
339 grpc_sopb_init(&g_sopb);
340 test();
341 grpc_chttp2_hpack_compressor_destroy(&g_compressor);
Craig Tiller9be83ee2015-02-18 14:16:15 -0800342 grpc_mdctx_unref(g_mdctx);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800343 grpc_sopb_destroy(&g_sopb);
344}
345
346int main(int argc, char **argv) {
Craig Tillerbd222712015-04-17 16:09:40 -0700347 int i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800348 grpc_test_init(argc, argv);
349 TEST(test_small_data_framing);
350 TEST(test_basic_headers);
351 TEST(test_decode_table_overflow);
352 TEST(test_decode_random_headers_1);
353 TEST(test_decode_random_headers_2);
354 TEST(test_decode_random_headers_3);
355 TEST(test_decode_random_headers_5);
356 TEST(test_decode_random_headers_8);
357 TEST(test_decode_random_headers_13);
358 TEST(test_decode_random_headers_21);
359 TEST(test_decode_random_headers_34);
360 TEST(test_decode_random_headers_55);
361 TEST(test_decode_random_headers_89);
362 TEST(test_decode_random_headers_144);
Craig Tillerbd222712015-04-17 16:09:40 -0700363 for (i = 0; i < num_to_delete; i++) {
364 gpr_free(to_delete[i]);
365 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800366 return g_failure;
Craig Tiller190d3602015-02-18 09:23:38 -0800367}