diff options
Diffstat (limited to 'test/core/transport/metadata_test.cc')
-rw-r--r-- | test/core/transport/metadata_test.cc | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/test/core/transport/metadata_test.cc b/test/core/transport/metadata_test.cc new file mode 100644 index 0000000000..4bc5672958 --- /dev/null +++ b/test/core/transport/metadata_test.cc @@ -0,0 +1,390 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/transport/metadata.h" + +#include <stdio.h> +#include <string.h> + +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> + +#include "src/core/ext/transport/chttp2/transport/bin_encoder.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/transport/static_metadata.h" +#include "test/core/util/test_config.h" + +/* a large number */ +#define MANY 10000 + +static void test_no_op(void) { + gpr_log(GPR_INFO, "test_no_op"); + grpc_init(); + grpc_shutdown(); +} + +static grpc_slice maybe_intern(grpc_slice in, bool intern) { + grpc_slice out = intern ? grpc_slice_intern(in) : grpc_slice_ref(in); + grpc_slice_unref(in); + return out; +} + +static grpc_slice maybe_dup(grpc_slice in, bool dup) { + grpc_slice out = dup ? grpc_slice_dup(in) : grpc_slice_ref(in); + grpc_slice_unref(in); + return out; +} + +static void test_create_metadata(bool intern_keys, bool intern_values) { + grpc_mdelem m1, m2, m3; + + gpr_log(GPR_INFO, "test_create_metadata: intern_keys=%d intern_values=%d", + intern_keys, intern_values); + + grpc_init(); + ExecCtx _local_exec_ctx; + m1 = grpc_mdelem_from_slices( + maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values)); + m2 = grpc_mdelem_from_slices( + maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values)); + m3 = grpc_mdelem_from_slices( + maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("c"), intern_values)); + GPR_ASSERT(grpc_mdelem_eq(m1, m2)); + GPR_ASSERT(!grpc_mdelem_eq(m3, m1)); + GPR_ASSERT(grpc_slice_eq(GRPC_MDKEY(m3), GRPC_MDKEY(m1))); + GPR_ASSERT(!grpc_slice_eq(GRPC_MDVALUE(m3), GRPC_MDVALUE(m1))); + GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDKEY(m1), "a") == 0); + GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(m1), "b") == 0); + GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(m3), "c") == 0); + GRPC_MDELEM_UNREF(m1); + GRPC_MDELEM_UNREF(m2); + GRPC_MDELEM_UNREF(m3); + grpc_exec_ctx_finish(); + grpc_shutdown(); +} + +static void test_create_many_ephemeral_metadata(bool intern_keys, + bool intern_values) { + char buffer[GPR_LTOA_MIN_BUFSIZE]; + long i; + + gpr_log( + GPR_INFO, + "test_create_many_ephemeral_metadata: intern_keys=%d intern_values=%d", + intern_keys, intern_values); + + grpc_init(); + ExecCtx _local_exec_ctx; + /* add, and immediately delete a bunch of different elements */ + for (i = 0; i < MANY; i++) { + gpr_ltoa(i, buffer); + GRPC_MDELEM_UNREF(grpc_mdelem_from_slices( + maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_copied_string(buffer), intern_values))); + } + grpc_exec_ctx_finish(); + grpc_shutdown(); +} + +static void test_create_many_persistant_metadata(void) { + char buffer[GPR_LTOA_MIN_BUFSIZE]; + long i; + grpc_mdelem* created = + static_cast<grpc_mdelem*>(gpr_malloc(sizeof(grpc_mdelem) * MANY)); + grpc_mdelem md; + + gpr_log(GPR_INFO, "test_create_many_persistant_metadata"); + + grpc_init(); + ExecCtx _local_exec_ctx; + /* add phase */ + for (i = 0; i < MANY; i++) { + gpr_ltoa(i, buffer); + created[i] = grpc_mdelem_from_slices( + grpc_slice_intern(grpc_slice_from_static_string("a")), + grpc_slice_intern(grpc_slice_from_static_string(buffer))); + } + /* verify phase */ + for (i = 0; i < MANY; i++) { + gpr_ltoa(i, buffer); + md = grpc_mdelem_from_slices( + grpc_slice_intern(grpc_slice_from_static_string("a")), + grpc_slice_intern(grpc_slice_from_static_string(buffer))); + GPR_ASSERT(grpc_mdelem_eq(md, created[i])); + GRPC_MDELEM_UNREF(md); + } + /* cleanup phase */ + for (i = 0; i < MANY; i++) { + GRPC_MDELEM_UNREF(created[i]); + } + grpc_exec_ctx_finish(); + grpc_shutdown(); + + gpr_free(created); +} + +static void test_spin_creating_the_same_thing(bool intern_keys, + bool intern_values) { + gpr_log(GPR_INFO, + "test_spin_creating_the_same_thing: intern_keys=%d intern_values=%d", + intern_keys, intern_values); + + grpc_init(); + ExecCtx _local_exec_ctx; + grpc_mdelem a, b, c; + GRPC_MDELEM_UNREF( + a = grpc_mdelem_from_slices( + maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values))); + GRPC_MDELEM_UNREF( + b = grpc_mdelem_from_slices( + maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values))); + GRPC_MDELEM_UNREF( + c = grpc_mdelem_from_slices( + maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values))); + if (intern_keys && intern_values) { + GPR_ASSERT(a.payload == b.payload); + GPR_ASSERT(a.payload == c.payload); + } + grpc_exec_ctx_finish(); + grpc_shutdown(); +} + +static void test_identity_laws(bool intern_keys, bool intern_values) { + gpr_log(GPR_INFO, "test_identity_laws: intern_keys=%d intern_values=%d", + intern_keys, intern_values); + + grpc_init(); + ExecCtx _local_exec_ctx; + grpc_mdelem a, b, c; + a = grpc_mdelem_from_slices( + maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values)); + b = grpc_mdelem_from_slices( + maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values)); + c = grpc_mdelem_from_slices( + maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values)); + GPR_ASSERT(grpc_mdelem_eq(a, a)); + GPR_ASSERT(grpc_mdelem_eq(b, b)); + GPR_ASSERT(grpc_mdelem_eq(c, c)); + GPR_ASSERT(grpc_mdelem_eq(a, b)); + GPR_ASSERT(grpc_mdelem_eq(b, c)); + GPR_ASSERT(grpc_mdelem_eq(a, c)); + GPR_ASSERT(grpc_mdelem_eq(b, a)); + GPR_ASSERT(grpc_mdelem_eq(c, b)); + GPR_ASSERT(grpc_mdelem_eq(c, a)); + if (intern_keys && intern_values) { + GPR_ASSERT(a.payload == b.payload); + GPR_ASSERT(a.payload == c.payload); + } else { + GPR_ASSERT(a.payload != b.payload); + GPR_ASSERT(a.payload != c.payload); + GPR_ASSERT(b.payload != c.payload); + } + GRPC_MDELEM_UNREF(a); + GRPC_MDELEM_UNREF(b); + GRPC_MDELEM_UNREF(c); + grpc_exec_ctx_finish(); + grpc_shutdown(); +} + +static void test_things_stick_around(void) { + size_t i, j; + char* buffer; + size_t nstrs = 1000; + grpc_slice* strs = + static_cast<grpc_slice*>(gpr_malloc(sizeof(grpc_slice) * nstrs)); + size_t* shuf = static_cast<size_t*>(gpr_malloc(sizeof(size_t) * nstrs)); + grpc_slice test; + + gpr_log(GPR_INFO, "test_things_stick_around"); + + grpc_init(); + ExecCtx _local_exec_ctx; + + for (i = 0; i < nstrs; i++) { + gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%" PRIuPTR "x", i); + strs[i] = grpc_slice_intern(grpc_slice_from_static_string(buffer)); + shuf[i] = i; + gpr_free(buffer); + } + + for (i = 0; i < nstrs; i++) { + grpc_slice_ref_internal(strs[i]); + grpc_slice_unref_internal(strs[i]); + } + + for (i = 0; i < nstrs; i++) { + size_t p = (size_t)rand() % nstrs; + size_t q = (size_t)rand() % nstrs; + size_t temp = shuf[p]; + shuf[p] = shuf[q]; + shuf[q] = temp; + } + + for (i = 0; i < nstrs; i++) { + grpc_slice_unref_internal(strs[shuf[i]]); + for (j = i + 1; j < nstrs; j++) { + gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%" PRIuPTR "x", + shuf[j]); + test = grpc_slice_intern(grpc_slice_from_static_string(buffer)); + GPR_ASSERT(grpc_slice_is_equivalent(test, strs[shuf[j]])); + grpc_slice_unref_internal(test); + gpr_free(buffer); + } + } + + grpc_exec_ctx_finish(); + grpc_shutdown(); + gpr_free(strs); + gpr_free(shuf); +} + +static void test_user_data_works(void) { + int* ud1; + int* ud2; + grpc_mdelem md; + gpr_log(GPR_INFO, "test_user_data_works"); + + grpc_init(); + ExecCtx _local_exec_ctx; + ud1 = static_cast<int*>(gpr_malloc(sizeof(int))); + *ud1 = 1; + ud2 = static_cast<int*>(gpr_malloc(sizeof(int))); + *ud2 = 2; + md = grpc_mdelem_from_slices( + grpc_slice_intern(grpc_slice_from_static_string("abc")), + grpc_slice_intern(grpc_slice_from_static_string("123"))); + grpc_mdelem_set_user_data(md, gpr_free, ud1); + grpc_mdelem_set_user_data(md, gpr_free, ud2); + GPR_ASSERT(grpc_mdelem_get_user_data(md, gpr_free) == ud1); + GRPC_MDELEM_UNREF(md); + grpc_exec_ctx_finish(); + grpc_shutdown(); +} + +static void verify_ascii_header_size(const char* key, const char* value, + bool intern_key, bool intern_value) { + grpc_mdelem elem = grpc_mdelem_from_slices( + maybe_intern(grpc_slice_from_static_string(key), intern_key), + maybe_intern(grpc_slice_from_static_string(value), intern_value)); + size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem, false); + size_t expected_size = 32 + strlen(key) + strlen(value); + GPR_ASSERT(expected_size == elem_size); + GRPC_MDELEM_UNREF(elem); +} + +static void verify_binary_header_size(const char* key, const uint8_t* value, + size_t value_len, bool intern_key, + bool intern_value) { + grpc_mdelem elem = grpc_mdelem_from_slices( + maybe_intern(grpc_slice_from_static_string(key), intern_key), + maybe_intern(grpc_slice_from_static_buffer(value, value_len), + intern_value)); + GPR_ASSERT(grpc_is_binary_header(GRPC_MDKEY(elem))); + size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem, false); + grpc_slice value_slice = + grpc_slice_from_copied_buffer((const char*)value, value_len); + grpc_slice base64_encoded = grpc_chttp2_base64_encode(value_slice); + size_t expected_size = 32 + strlen(key) + GRPC_SLICE_LENGTH(base64_encoded); + GPR_ASSERT(expected_size == elem_size); + grpc_slice_unref_internal(value_slice); + grpc_slice_unref_internal(base64_encoded); + GRPC_MDELEM_UNREF(elem); +} + +#define BUFFER_SIZE 64 +static void test_mdelem_sizes_in_hpack(bool intern_key, bool intern_value) { + gpr_log(GPR_INFO, "test_mdelem_size: intern_key=%d intern_value=%d", + intern_key, intern_value); + grpc_init(); + ExecCtx _local_exec_ctx; + + uint8_t binary_value[BUFFER_SIZE] = {0}; + for (uint8_t i = 0; i < BUFFER_SIZE; i++) { + binary_value[i] = i; + } + + verify_ascii_header_size("hello", "world", intern_key, intern_value); + verify_ascii_header_size("hello", "worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + intern_key, intern_value); + verify_ascii_header_size(":scheme", "http", intern_key, intern_value); + + for (uint8_t i = 0; i < BUFFER_SIZE; i++) { + verify_binary_header_size("hello-bin", binary_value, i, intern_key, + intern_value); + } + + grpc_exec_ctx_finish(); + grpc_shutdown(); +} + +static void test_copied_static_metadata(bool dup_key, bool dup_value) { + gpr_log(GPR_INFO, "test_static_metadata: dup_key=%d dup_value=%d", dup_key, + dup_value); + grpc_init(); + ExecCtx _local_exec_ctx; + + for (size_t i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) { + grpc_mdelem p = GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[i], + GRPC_MDELEM_STORAGE_STATIC); + grpc_mdelem q = + grpc_mdelem_from_slices(maybe_dup(GRPC_MDKEY(p), dup_key), + maybe_dup(GRPC_MDVALUE(p), dup_value)); + GPR_ASSERT(grpc_mdelem_eq(p, q)); + if (dup_key || dup_value) { + GPR_ASSERT(p.payload != q.payload); + } else { + GPR_ASSERT(p.payload == q.payload); + } + GRPC_MDELEM_UNREF(p); + GRPC_MDELEM_UNREF(q); + } + + grpc_exec_ctx_finish(); + grpc_shutdown(); +} + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + test_no_op(); + for (int k = 0; k <= 1; k++) { + for (int v = 0; v <= 1; v++) { + test_create_metadata(k, v); + test_create_many_ephemeral_metadata(k, v); + test_identity_laws(k, v); + test_spin_creating_the_same_thing(k, v); + test_mdelem_sizes_in_hpack(k, v); + test_copied_static_metadata(k, v); + } + } + test_create_many_persistant_metadata(); + test_things_stick_around(); + test_user_data_works(); + return 0; +} |