blob: b23e999c529b18ea0d10fdd58eae6c2c75bc3f58 [file] [log] [blame]
Craig Tiller93b94472015-11-02 14:18:30 -08001/*
2 *
Craig Tiller2e190362016-03-25 14:33:26 -07003 * Copyright 2015-2016, Google Inc.
Craig Tiller93b94472015-11-02 14:18:30 -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
Craig Tiller9533d042016-03-25 17:11:06 -070034#include "src/core/lib/transport/chttp2/hpack_encoder.h"
Craig Tiller93b94472015-11-02 14:18:30 -080035
36#include <stdio.h>
37
Craig Tiller93b94472015-11-02 14:18:30 -080038#include <grpc/support/alloc.h>
39#include <grpc/support/log.h>
40#include <grpc/support/string_util.h>
Craig Tiller9533d042016-03-25 17:11:06 -070041#include "src/core/lib/support/string.h"
42#include "src/core/lib/transport/chttp2/hpack_parser.h"
43#include "src/core/lib/transport/metadata.h"
Craig Tiller93b94472015-11-02 14:18:30 -080044#include "test/core/util/parse_hexstring.h"
45#include "test/core/util/slice_splitter.h"
46#include "test/core/util/test_config.h"
47
48#define TEST(x) run_test(x, #x)
49
Craig Tiller93b94472015-11-02 14:18:30 -080050grpc_chttp2_hpack_compressor g_compressor;
51int g_failure = 0;
52
53void **to_delete = NULL;
54size_t num_to_delete = 0;
55size_t cap_to_delete = 0;
56
57/* verify that the output generated by encoding the stream matches the
58 hexstring passed in */
59static void verify(size_t window_available, int eof, size_t expect_window_used,
60 const char *expected, size_t nheaders, ...) {
61 gpr_slice_buffer output;
62 gpr_slice merged;
63 gpr_slice expect = parse_hexstring(expected);
64 size_t i;
65 va_list l;
66 grpc_linked_mdelem *e = gpr_malloc(sizeof(*e) * nheaders);
67 grpc_metadata_batch b;
68
69 grpc_metadata_batch_init(&b);
70
71 va_start(l, nheaders);
72 for (i = 0; i < nheaders; i++) {
73 char *key = va_arg(l, char *);
74 char *value = va_arg(l, char *);
75 if (i) {
76 e[i - 1].next = &e[i];
77 e[i].prev = &e[i - 1];
78 }
Craig Tillerb2b42612015-11-20 12:02:17 -080079 e[i].md = grpc_mdelem_from_strings(key, value);
Craig Tiller93b94472015-11-02 14:18:30 -080080 }
81 e[0].prev = NULL;
82 e[nheaders - 1].next = NULL;
83 va_end(l);
84
85 b.list.head = &e[0];
86 b.list.tail = &e[nheaders - 1];
87
88 if (cap_to_delete == num_to_delete) {
89 cap_to_delete = GPR_MAX(2 * cap_to_delete, 1000);
90 to_delete = gpr_realloc(to_delete, sizeof(*to_delete) * cap_to_delete);
91 }
92 to_delete[num_to_delete++] = e;
93
94 gpr_slice_buffer_init(&output);
95
96 grpc_chttp2_encode_header(&g_compressor, 0xdeadbeef, &b, eof, &output);
97 merged = grpc_slice_merge(output.slices, output.count);
98 gpr_slice_buffer_destroy(&output);
99 grpc_metadata_batch_destroy(&b);
100
101 if (0 != gpr_slice_cmp(merged, expect)) {
102 char *expect_str = gpr_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII);
103 char *got_str = gpr_dump_slice(merged, GPR_DUMP_HEX | GPR_DUMP_ASCII);
104 gpr_log(GPR_ERROR, "mismatched output for %s", expected);
105 gpr_log(GPR_ERROR, "EXPECT: %s", expect_str);
106 gpr_log(GPR_ERROR, "GOT: %s", got_str);
107 gpr_free(expect_str);
108 gpr_free(got_str);
109 g_failure = 1;
110 }
111
112 gpr_slice_unref(merged);
113 gpr_slice_unref(expect);
114}
115
116static void test_basic_headers(void) {
117 int i;
118
119 verify(0, 0, 0, "000005 0104 deadbeef 40 0161 0161", 1, "a", "a");
120 verify(0, 0, 0, "000001 0104 deadbeef be", 1, "a", "a");
121 verify(0, 0, 0, "000001 0104 deadbeef be", 1, "a", "a");
122 verify(0, 0, 0, "000006 0104 deadbeef be 40 0162 0163", 2, "a", "a", "b",
123 "c");
124 verify(0, 0, 0, "000002 0104 deadbeef bf be", 2, "a", "a", "b", "c");
125 verify(0, 0, 0, "000004 0104 deadbeef 7f 00 0164", 1, "a", "d");
126
127 /* flush out what's there to make a few values look very popular */
128 for (i = 0; i < 350; i++) {
129 verify(0, 0, 0, "000003 0104 deadbeef c0 bf be", 3, "a", "a", "b", "c", "a",
130 "d");
131 }
132
133 verify(0, 0, 0, "000006 0104 deadbeef c0 00 016b 0176", 2, "a", "a", "k",
134 "v");
135 /* this could be 000004 0104 deadbeef 0f 30 0176 also */
136 verify(0, 0, 0, "000004 0104 deadbeef 0f 2f 0176", 1, "a", "v");
137}
138
139static void encode_int_to_str(int i, char *p) {
140 p[0] = (char)('a' + i % 26);
141 i /= 26;
142 GPR_ASSERT(i < 26);
143 p[1] = (char)('a' + i);
144 p[2] = 0;
145}
146
147static void test_decode_table_overflow(void) {
148 int i;
149 char key[3], value[3];
150 char *expect;
151
152 for (i = 0; i < 114; i++) {
153 encode_int_to_str(i, key);
154 encode_int_to_str(i + 1, value);
155
156 if (i + 61 >= 127) {
157 gpr_asprintf(&expect,
158 "000009 0104 deadbeef ff%02x 40 02%02x%02x 02%02x%02x",
159 i + 61 - 127, key[0], key[1], value[0], value[1]);
160 } else if (i > 0) {
161 gpr_asprintf(&expect,
162 "000008 0104 deadbeef %02x 40 02%02x%02x 02%02x%02x",
163 0x80 + 61 + i, key[0], key[1], value[0], value[1]);
164 } else {
165 gpr_asprintf(&expect, "000007 0104 deadbeef 40 02%02x%02x 02%02x%02x",
166 key[0], key[1], value[0], value[1]);
167 }
168
169 if (i > 0) {
170 verify(0, 0, 0, expect, 2, "aa", "ba", key, value);
171 } else {
172 verify(0, 0, 0, expect, 1, key, value);
173 }
174 gpr_free(expect);
175 }
176
177 /* if the above passes, then we must have just knocked this pair out of the
178 decoder stack, and so we'll be forced to re-encode it */
179 verify(0, 0, 0, "000007 0104 deadbeef 40 026161 026261", 1, "aa", "ba");
180}
181
182static void run_test(void (*test)(), const char *name) {
183 gpr_log(GPR_INFO, "RUN TEST: %s", name);
Craig Tillerb2b42612015-11-20 12:02:17 -0800184 grpc_chttp2_hpack_compressor_init(&g_compressor);
Craig Tiller93b94472015-11-02 14:18:30 -0800185 test();
186 grpc_chttp2_hpack_compressor_destroy(&g_compressor);
Craig Tiller93b94472015-11-02 14:18:30 -0800187}
188
189int main(int argc, char **argv) {
190 size_t i;
Craig Tillere62bf982015-12-02 17:11:49 -0800191 grpc_test_only_set_metadata_hash_seed(0);
Craig Tiller93b94472015-11-02 14:18:30 -0800192 grpc_test_init(argc, argv);
Craig Tiller0e72ede2015-11-19 07:48:53 -0800193 grpc_init();
Craig Tiller93b94472015-11-02 14:18:30 -0800194 TEST(test_basic_headers);
195 TEST(test_decode_table_overflow);
Craig Tiller0e72ede2015-11-19 07:48:53 -0800196 grpc_shutdown();
Craig Tiller93b94472015-11-02 14:18:30 -0800197 for (i = 0; i < num_to_delete; i++) {
198 gpr_free(to_delete[i]);
199 }
200 return g_failure;
201}