hpack_encoder_test.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
20 
21 #include <stdio.h>
22 #include <string.h>
23 
24 #include <string>
25 
26 #include "absl/strings/str_cat.h"
27 #include "absl/strings/str_format.h"
28 
29 #include <grpc/grpc.h>
30 #include <grpc/support/alloc.h>
31 #include <grpc/support/log.h>
32 
41 
42 #define TEST(x) run_test(x, #x)
43 
45  grpc_core::ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
46  "test"));
47 
49 int g_failure = 0;
50 
51 typedef struct {
52  bool eof;
55 
56 /* verify that the output frames that are generated by encoding the stream
57  have sensible type and flags values */
58 static void verify_frames(grpc_slice_buffer& output, bool header_is_eof) {
59  /* per the HTTP/2 spec:
60  All frames begin with a fixed 9-octet header followed by a
61  variable-length payload.
62 
63  +-----------------------------------------------+
64  | Length (24) |
65  +---------------+---------------+---------------+
66  | Type (8) | Flags (8) |
67  +-+-------------+---------------+-------------------------------+
68  |R| Stream Identifier (31) |
69  +=+=============================================================+
70  | Frame Payload (0...) ...
71  +---------------------------------------------------------------+
72  */
73  uint8_t type = 0xff, flags = 0xff;
74  size_t i, merged_length, frame_size;
75  bool first_frame = false;
76  bool in_header = false;
77  bool end_header = false;
78  bool is_closed = false;
79  for (i = 0; i < output.count;) {
80  first_frame = i == 0;
81  grpc_slice* slice = &output.slices[i++];
82 
83  // Read gRPC frame header
85  frame_size = 0;
86  frame_size |= static_cast<uint32_t>(p[0]) << 16;
87  frame_size |= static_cast<uint32_t>(p[1]) << 8;
88  frame_size |= static_cast<uint32_t>(p[2]);
89  type = p[3];
90  flags = p[4];
91 
92  // Read remainder of the gRPC frame
93  merged_length = GRPC_SLICE_LENGTH(*slice);
94  while (merged_length < frame_size + 9) { // including 9 byte frame header
95  grpc_slice* slice = &output.slices[i++];
96  merged_length += GRPC_SLICE_LENGTH(*slice);
97  }
98 
99  // Verifications
100  if (first_frame && type != GRPC_CHTTP2_FRAME_HEADER) {
101  gpr_log(GPR_ERROR, "expected first frame to be of type header");
102  gpr_log(GPR_ERROR, "EXPECT: 0x%x", GRPC_CHTTP2_FRAME_HEADER);
103  gpr_log(GPR_ERROR, "GOT: 0x%x", type);
104  g_failure = 1;
105  } else if (first_frame && header_is_eof &&
107  gpr_log(GPR_ERROR, "missing END_STREAM flag in HEADER frame");
108  g_failure = 1;
109  }
110  if (is_closed &&
113  "stream is closed; new frame headers and data are not allowed");
114  g_failure = 1;
115  }
116  if (end_header && (type == GRPC_CHTTP2_FRAME_HEADER ||
119  "frame header is ended; new headers and continuations are not "
120  "allowed");
121  g_failure = 1;
122  }
123  if (in_header &&
126  "parsing frame header; new headers and data are not allowed");
127  g_failure = 1;
128  }
131  gpr_log(GPR_ERROR, "unexpected frame flags: 0x%x", flags);
132  g_failure = 1;
133  }
134 
135  // Update state
137  in_header = false;
138  end_header = true;
139  } else if (type == GRPC_CHTTP2_DATA_FLAG_END_HEADERS) {
140  in_header = true;
141  }
143  is_closed = true;
145  gpr_log(GPR_ERROR, "unexpected END_STREAM flag in CONTINUATION frame");
146  g_failure = 1;
147  }
148  }
149  }
150 }
151 
153  abort();
154 }
155 
156 /* verify that the output generated by encoding the stream matches the
157  hexstring passed in */
158 static void verify(const verify_params params, const char* expected,
159  size_t nheaders, ...) {
161  grpc_slice merged;
162  grpc_slice expect = parse_hexstring(expected);
163  size_t i;
164  va_list l;
166  grpc_metadata_batch b(arena.get());
167 
168  va_start(l, nheaders);
169  for (i = 0; i < nheaders; i++) {
170  char* key = va_arg(l, char*);
171  char* value = va_arg(l, char*);
174  }
175  va_end(l);
176 
178 
180  stats = {};
182  0xdeadbeef, /* stream_id */
183  params.eof, /* is_eof */
184  params.use_true_binary_metadata, /* use_true_binary_metadata */
185  16384, /* max_frame_size */
186  &stats /* stats */
187  };
189  verify_frames(output, params.eof);
190  merged = grpc_slice_merge(output.slices, output.count);
192 
193  if (!grpc_slice_eq(merged, expect)) {
194  char* expect_str = grpc_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII);
195  char* got_str = grpc_dump_slice(merged, GPR_DUMP_HEX | GPR_DUMP_ASCII);
196  gpr_log(GPR_ERROR, "mismatched output for %s", expected);
197  gpr_log(GPR_ERROR, "EXPECT: %s", expect_str);
198  gpr_log(GPR_ERROR, "GOT: %s", got_str);
199  gpr_free(expect_str);
200  gpr_free(got_str);
201  g_failure = 1;
202  }
203 
206 }
207 
208 static void test_basic_headers() {
209  verify_params params = {
210  false,
211  false,
212  };
213  verify(params, "000005 0104 deadbeef 00 0161 0161", 1, "a", "a");
214  verify(params, "00000a 0104 deadbeef 00 0161 0161 00 0162 0163", 2, "a", "a",
215  "b", "c");
216 }
217 
218 static void verify_continuation_headers(const char* key, const char* value,
219  bool is_eof) {
222  grpc_metadata_batch b(arena.get());
225 
227  stats = {};
229  0xdeadbeef, /* stream_id */
230  is_eof, /* is_eof */
231  false, /* use_true_binary_metadata */
232  150, /* max_frame_size */
233  &stats /* stats */};
235  verify_frames(output, is_eof);
237 }
238 
240  char value[200];
241  memset(value, 'a', 200);
242  value[199] = 0; // null terminator
243  verify_continuation_headers("key", value, true);
244 
245  char value2[400];
246  memset(value2, 'b', 400);
247  value2[399] = 0; // null terminator
248  verify_continuation_headers("key2", value2, true);
249 }
250 
251 static void run_test(void (*test)(), const char* name) {
252  gpr_log(GPR_INFO, "RUN TEST: %s", name);
255  test();
256  delete g_compressor;
257 }
258 
259 int main(int argc, char** argv) {
261  grpc::testing::TestEnvironment env(&argc, argv);
262  grpc_init();
265  grpc_shutdown();
266  return g_failure;
267 }
grpc_core::MakeScopedArena
ScopedArenaPtr MakeScopedArena(size_t initial_size, MemoryAllocator *memory_allocator)
Definition: src/core/lib/resource_quota/arena.h:130
GPR_INFO
#define GPR_INFO
Definition: include/grpc/impl/codegen/log.h:56
log.h
generate.env
env
Definition: generate.py:37
memset
return memset(p, 0, total)
grpc_event_engine::experimental::MemoryAllocator
Definition: memory_allocator.h:35
grpc_dump_slice
char * grpc_dump_slice(const grpc_slice &s, uint32_t flags)
Definition: slice_string_helpers.cc:25
verify_params
Definition: hpack_encoder_test.cc:51
test
Definition: spinlock_test.cc:36
grpc_core::Slice
Definition: src/core/lib/slice/slice.h:282
string.h
grpc_core::slice_detail::StaticConstructors< Slice >::FromStaticString
static Slice FromStaticString(const char *s)
Definition: src/core/lib/slice/slice.h:201
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
gpr_free
GPRAPI void gpr_free(void *ptr)
Definition: alloc.cc:51
GRPC_CHTTP2_DATA_FLAG_END_HEADERS
#define GRPC_CHTTP2_DATA_FLAG_END_HEADERS
Definition: frame.h:39
setup.name
name
Definition: setup.py:542
xds_manager.p
p
Definition: xds_manager.py:60
GPR_DUMP_HEX
#define GPR_DUMP_HEX
Definition: string.h:34
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
grpc_core::HPackCompressor::EncodeHeaders
void EncodeHeaders(const EncodeHeaderOptions &options, const HeaderSet &headers, grpc_slice_buffer *output)
Definition: hpack_encoder.h:77
verify_params::eof
bool eof
Definition: hpack_encoder_test.cc:52
verify
static void verify(const verify_params params, const char *expected, size_t nheaders,...)
Definition: hpack_encoder_test.cc:158
GPR_DUMP_ASCII
#define GPR_DUMP_ASCII
Definition: string.h:35
TEST
#define TEST(x)
Definition: hpack_encoder_test.cc:42
GRPC_CHTTP2_FRAME_HEADER
#define GRPC_CHTTP2_FRAME_HEADER
Definition: frame.h:29
arena
grpc_core::ScopedArenaPtr arena
Definition: binder_transport_test.cc:237
grpc_core::HPackCompressor::EncodeHeaderOptions
Definition: hpack_encoder.h:68
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
g_compressor
grpc_core::HPackCompressor * g_compressor
Definition: hpack_encoder_test.cc:48
slice_splitter.h
hpack_parser.h
verify_params::use_true_binary_metadata
bool use_true_binary_metadata
Definition: hpack_encoder_test.cc:53
grpc_test_only_set_slice_hash_seed
void grpc_test_only_set_slice_hash_seed(uint32_t seed)
Definition: slice_refcount.cc:33
grpc_core::HPackCompressor
Definition: hpack_encoder.h:51
gmock_output_test.output
output
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
slice
grpc_slice slice
Definition: src/core/lib/surface/server.cc:467
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
grpc.h
gen_stats_data.stats
list stats
Definition: gen_stats_data.py:58
GRPC_SLICE_START_PTR
#define GRPC_SLICE_START_PTR(slice)
Definition: include/grpc/impl/codegen/slice.h:101
GRPC_CHTTP2_FRAME_CONTINUATION
#define GRPC_CHTTP2_FRAME_CONTINUATION
Definition: frame.h:30
grpc_slice
Definition: include/grpc/impl/codegen/slice.h:65
grpc_core::ResourceQuota::Default
static ResourceQuotaRefPtr Default()
Definition: resource_quota.cc:27
grpc_slice_merge
grpc_slice grpc_slice_merge(grpc_slice *slices, size_t nslices)
Definition: slice_splitter.cc:111
slice_internal.h
GPR_ERROR
#define GPR_ERROR
Definition: include/grpc/impl/codegen/log.h:57
run_test
static void run_test(void(*test)(), const char *name)
Definition: hpack_encoder_test.cc:251
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
resource_quota.h
grpc_transport_one_way_stats
Definition: transport.h:243
grpc_core::ExecCtx
Definition: exec_ctx.h:97
grpc_slice_buffer_init
GPRAPI void grpc_slice_buffer_init(grpc_slice_buffer *sb)
Definition: slice/slice_buffer.cc:116
GRPC_SLICE_LENGTH
#define GRPC_SLICE_LENGTH(slice)
Definition: include/grpc/impl/codegen/slice.h:104
test_config.h
value
const char * value
Definition: hpack_parser_table.cc:165
update_failure_list.test
test
Definition: bloaty/third_party/protobuf/conformance/update_failure_list.py:69
key
const char * key
Definition: hpack_parser_table.cc:164
absl::flags_internal
Definition: abseil-cpp/absl/flags/commandlineflag.h:40
test_continuation_headers
static void test_continuation_headers()
Definition: hpack_encoder_test.cc:239
exec_ctx
grpc_core::ExecCtx exec_ctx
Definition: end2end_binder_transport_test.cc:75
CrashOnAppendError
static void CrashOnAppendError(absl::string_view, const grpc_core::Slice &)
Definition: hpack_encoder_test.cc:152
verify_frames
static void verify_frames(grpc_slice_buffer &output, bool header_is_eof)
Definition: hpack_encoder_test.cc:58
GRPC_CHTTP2_DATA_FLAG_END_STREAM
#define GRPC_CHTTP2_DATA_FLAG_END_STREAM
Definition: frame.h:37
GRPC_CHTTP2_FRAME_DATA
#define GRPC_CHTTP2_FRAME_DATA
Definition: frame.h:28
alloc.h
g_failure
int g_failure
Definition: hpack_encoder_test.cc:49
grpc::testing::TestEnvironment
Definition: test/core/util/test_config.h:54
test_basic_headers
static void test_basic_headers()
Definition: hpack_encoder_test.cc:208
verify_continuation_headers
static void verify_continuation_headers(const char *key, const char *value, bool is_eof)
Definition: hpack_encoder_test.cc:218
hpack_encoder.h
g_memory_allocator
static auto * g_memory_allocator
Definition: hpack_encoder_test.cc:44
grpc_slice_buffer_destroy_internal
void grpc_slice_buffer_destroy_internal(grpc_slice_buffer *sb)
Definition: slice/slice_buffer.cc:123
grpc_slice_buffer
Definition: include/grpc/impl/codegen/slice.h:83
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
grpc_init
GRPCAPI void grpc_init(void)
Definition: init.cc:146
run_grpclb_interop_tests.l
dictionary l
Definition: run_grpclb_interop_tests.py:410
parse_hexstring.h
grpc_metadata_batch
Definition: metadata_batch.h:1259
parse_hexstring
grpc_slice parse_hexstring(const char *hexstring)
Definition: parse_hexstring.cc:23
grpc_slice_eq
GPRAPI int grpc_slice_eq(grpc_slice a, grpc_slice b)
Definition: slice/slice.cc:387
grpc_shutdown
GRPCAPI void grpc_shutdown(void)
Definition: init.cc:209
main
int main(int argc, char **argv)
Definition: hpack_encoder_test.cc:259
slice_string_helpers.h
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
grpc_slice_unref_internal
void grpc_slice_unref_internal(const grpc_slice &slice)
Definition: slice_refcount.h:39


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:13