diff options
author | 2017-12-06 18:47:16 -0800 | |
---|---|---|
committer | 2017-12-06 18:47:16 -0800 | |
commit | 4a117f0be7feb1779bd0bb0b65c6e2d930f07e80 (patch) | |
tree | 30ca52f7141db8fc8543a5a0bc7842766fab5c12 /test/core | |
parent | 1b1c9b387bcd98f08b8c17f6ee15095c099dd665 (diff) | |
parent | 4f22c919e1207af206fc83e7378f04e047f7c78d (diff) |
Merge e759d2a^
Diffstat (limited to 'test/core')
75 files changed, 1287 insertions, 2226 deletions
diff --git a/test/core/backoff/backoff_test.c b/test/core/backoff/backoff_test.c index 3848b2a54d..e80e0b31b8 100644 --- a/test/core/backoff/backoff_test.c +++ b/test/core/backoff/backoff_test.c @@ -19,119 +19,157 @@ #include "src/core/lib/backoff/backoff.h" #include <grpc/support/log.h> +#include <grpc/support/useful.h> #include "test/core/util/test_config.h" static void test_constant_backoff(void) { grpc_backoff backoff; - grpc_backoff_init(&backoff, 200 /* initial timeout */, 1.0 /* multiplier */, - 0.0 /* jitter */, 100 /* min timeout */, - 1000 /* max timeout */); - + const grpc_millis initial_backoff = 200; + const double multiplier = 1.0; + const double jitter = 0.0; + const grpc_millis min_connect_timeout = 100; + const grpc_millis max_backoff = 1000; + grpc_backoff_init(&backoff, initial_backoff, multiplier, jitter, + min_connect_timeout, max_backoff); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_millis next = grpc_backoff_begin(&exec_ctx, &backoff); - GPR_ASSERT(next - grpc_exec_ctx_now(&exec_ctx) == 200); + grpc_backoff_result next_deadlines = grpc_backoff_begin(&exec_ctx, &backoff); + GPR_ASSERT(next_deadlines.current_deadline - grpc_exec_ctx_now(&exec_ctx) == + initial_backoff); + GPR_ASSERT(next_deadlines.next_attempt_start_time - + grpc_exec_ctx_now(&exec_ctx) == + initial_backoff); for (int i = 0; i < 10000; i++) { - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next - grpc_exec_ctx_now(&exec_ctx) == 200); - exec_ctx.now = next; + next_deadlines = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next_deadlines.current_deadline - grpc_exec_ctx_now(&exec_ctx) == + initial_backoff); + GPR_ASSERT(next_deadlines.next_attempt_start_time - + grpc_exec_ctx_now(&exec_ctx) == + initial_backoff); + exec_ctx.now = next_deadlines.current_deadline; } grpc_exec_ctx_finish(&exec_ctx); } static void test_min_connect(void) { grpc_backoff backoff; - grpc_backoff_init(&backoff, 100 /* initial timeout */, 1.0 /* multiplier */, - 0.0 /* jitter */, 200 /* min timeout */, - 1000 /* max timeout */); - + const grpc_millis initial_backoff = 100; + const double multiplier = 1.0; + const double jitter = 0.0; + const grpc_millis min_connect_timeout = 200; + const grpc_millis max_backoff = 1000; + grpc_backoff_init(&backoff, initial_backoff, multiplier, jitter, + min_connect_timeout, max_backoff); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_millis next = grpc_backoff_begin(&exec_ctx, &backoff); - GPR_ASSERT(next - grpc_exec_ctx_now(&exec_ctx) == 200); + grpc_backoff_result next = grpc_backoff_begin(&exec_ctx, &backoff); + // Because the min_connect_timeout > initial_backoff, current_deadline is used + // as the deadline for the current attempt. + GPR_ASSERT(next.current_deadline - grpc_exec_ctx_now(&exec_ctx) == + min_connect_timeout); + // ... while, if the current attempt fails, the next one will happen after + // initial_backoff. + GPR_ASSERT(next.next_attempt_start_time - grpc_exec_ctx_now(&exec_ctx) == + initial_backoff); grpc_exec_ctx_finish(&exec_ctx); } static void test_no_jitter_backoff(void) { grpc_backoff backoff; - grpc_backoff_init(&backoff, 2 /* initial timeout */, 2.0 /* multiplier */, - 0.0 /* jitter */, 1 /* min timeout */, - 513 /* max timeout */); + const grpc_millis initial_backoff = 2; + const double multiplier = 2.0; + const double jitter = 0.0; + const grpc_millis min_connect_timeout = 1; + const grpc_millis max_backoff = 513; + grpc_backoff_init(&backoff, initial_backoff, multiplier, jitter, + min_connect_timeout, max_backoff); // x_1 = 2 // x_n = 2**i + x_{i-1} ( = 2**(n+1) - 2 ) grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; exec_ctx.now = 0; exec_ctx.now_is_valid = true; - grpc_millis next = grpc_backoff_begin(&exec_ctx, &backoff); - GPR_ASSERT(next == 2); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 6); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 14); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 30); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 62); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 126); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 254); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 510); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 1022); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); + grpc_backoff_result next_deadlines = grpc_backoff_begin(&exec_ctx, &backoff); + GPR_ASSERT(next_deadlines.current_deadline == + next_deadlines.next_attempt_start_time); + GPR_ASSERT(next_deadlines.current_deadline == 2); + exec_ctx.now = next_deadlines.current_deadline; + next_deadlines = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next_deadlines.current_deadline == 6); + exec_ctx.now = next_deadlines.current_deadline; + next_deadlines = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next_deadlines.current_deadline == 14); + exec_ctx.now = next_deadlines.current_deadline; + next_deadlines = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next_deadlines.current_deadline == 30); + exec_ctx.now = next_deadlines.current_deadline; + next_deadlines = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next_deadlines.current_deadline == 62); + exec_ctx.now = next_deadlines.current_deadline; + next_deadlines = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next_deadlines.current_deadline == 126); + exec_ctx.now = next_deadlines.current_deadline; + next_deadlines = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next_deadlines.current_deadline == 254); + exec_ctx.now = next_deadlines.current_deadline; + next_deadlines = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next_deadlines.current_deadline == 510); + exec_ctx.now = next_deadlines.current_deadline; + next_deadlines = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next_deadlines.current_deadline == 1022); + exec_ctx.now = next_deadlines.current_deadline; + next_deadlines = grpc_backoff_step(&exec_ctx, &backoff); // Hit the maximum timeout. From this point onwards, retries will increase // only by max timeout. - GPR_ASSERT(next == 1535); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 2048); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 2561); + GPR_ASSERT(next_deadlines.current_deadline == 1535); + exec_ctx.now = next_deadlines.current_deadline; + next_deadlines = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next_deadlines.current_deadline == 2048); + exec_ctx.now = next_deadlines.current_deadline; + next_deadlines = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next_deadlines.current_deadline == 2561); grpc_exec_ctx_finish(&exec_ctx); } static void test_jitter_backoff(void) { - const int64_t initial_timeout = 500; + const grpc_millis initial_backoff = 500; + grpc_millis current_backoff = initial_backoff; + const grpc_millis max_backoff = 1000; + const grpc_millis min_connect_timeout = 100; + const double multiplier = 1.0; const double jitter = 0.1; grpc_backoff backoff; - grpc_backoff_init(&backoff, initial_timeout, 1.0 /* multiplier */, jitter, - 100 /* min timeout */, 1000 /* max timeout */); + grpc_backoff_init(&backoff, initial_backoff, multiplier, jitter, + min_connect_timeout, max_backoff); backoff.rng_state = 0; // force consistent PRNG grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_millis next = grpc_backoff_begin(&exec_ctx, &backoff); - GPR_ASSERT(next - grpc_exec_ctx_now(&exec_ctx) == 500); - - int64_t expected_next_lower_bound = - (int64_t)((double)initial_timeout * (1 - jitter)); - int64_t expected_next_upper_bound = - (int64_t)((double)initial_timeout * (1 + jitter)); + grpc_backoff_result next_deadlines = grpc_backoff_begin(&exec_ctx, &backoff); + GPR_ASSERT(next_deadlines.current_deadline - grpc_exec_ctx_now(&exec_ctx) == + initial_backoff); + GPR_ASSERT(next_deadlines.next_attempt_start_time - + grpc_exec_ctx_now(&exec_ctx) == + initial_backoff); + + grpc_millis expected_next_lower_bound = + (grpc_millis)((double)current_backoff * (1 - jitter)); + grpc_millis expected_next_upper_bound = + (grpc_millis)((double)current_backoff * (1 + jitter)); for (int i = 0; i < 10000; i++) { - next = grpc_backoff_step(&exec_ctx, &backoff); - - // next-now must be within (jitter*100)% of the previous timeout. - const int64_t timeout_millis = next - grpc_exec_ctx_now(&exec_ctx); + next_deadlines = grpc_backoff_step(&exec_ctx, &backoff); + // next-now must be within (jitter*100)% of the current backoff (which + // increases by * multiplier up to max_backoff). + const grpc_millis timeout_millis = + next_deadlines.current_deadline - grpc_exec_ctx_now(&exec_ctx); GPR_ASSERT(timeout_millis >= expected_next_lower_bound); GPR_ASSERT(timeout_millis <= expected_next_upper_bound); - + current_backoff = GPR_MIN( + (grpc_millis)((double)current_backoff * multiplier), max_backoff); expected_next_lower_bound = - (int64_t)((double)timeout_millis * (1 - jitter)); + (grpc_millis)((double)current_backoff * (1 - jitter)); expected_next_upper_bound = - (int64_t)((double)timeout_millis * (1 + jitter)); - exec_ctx.now = next; + (grpc_millis)((double)current_backoff * (1 + jitter)); + exec_ctx.now = next_deadlines.current_deadline; } grpc_exec_ctx_finish(&exec_ctx); } diff --git a/test/core/bad_client/gen_build_yaml.py b/test/core/bad_client/gen_build_yaml.py index dbd52777e1..61cf1f7cd7 100755 --- a/test/core/bad_client/gen_build_yaml.py +++ b/test/core/bad_client/gen_build_yaml.py @@ -30,7 +30,7 @@ BAD_CLIENT_TESTS = { 'headers': default_test_options._replace(cpu_cost=0.2), 'initial_settings_frame': default_test_options._replace(cpu_cost=0.2), 'head_of_line_blocking': default_test_options, - 'large_metadata': default_test_options, + # 'large_metadata': default_test_options, #disabling as per issue #11745 'server_registered_method': default_test_options, 'simple_request': default_test_options, 'window_overflow': default_test_options, diff --git a/test/core/bad_client/generate_tests.bzl b/test/core/bad_client/generate_tests.bzl index 1aeb81c00d..58b48d688f 100755 --- a/test/core/bad_client/generate_tests.bzl +++ b/test/core/bad_client/generate_tests.bzl @@ -28,7 +28,7 @@ BAD_CLIENT_TESTS = { 'headers': test_options(), 'initial_settings_frame': test_options(), 'head_of_line_blocking': test_options(), - 'large_metadata': test_options(), + # 'large_metadata': test_options(), # disabling as per issue #11745 'server_registered_method': test_options(), 'simple_request': test_options(), 'window_overflow': test_options(), diff --git a/test/core/census/BUILD b/test/core/census/BUILD deleted file mode 100644 index 24fd2807d0..0000000000 --- a/test/core/census/BUILD +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright 2016 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. - -load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package") - -grpc_package(name = "test/core/census") - -licenses(["notice"]) # Apache v2 - -grpc_cc_test( - name = "context_test", - srcs = ["context_test.c"], - language = "C", - deps = [ - "//:gpr", - "//:grpc", - "//test/core/util:gpr_test_util", - "//test/core/util:grpc_test_util", - ], -) - -grpc_cc_test( - name = "mlog_test", - srcs = ["mlog_test.c"], - language = "C", - deps = [ - "//:gpr", - "//:grpc", - "//test/core/util:gpr_test_util", - "//test/core/util:grpc_test_util", - ], -) - -grpc_cc_test( - name = "resource_test", - srcs = ["resource_test.c"], - language = "C", - data = [ - ":data/resource_empty_name.pb", - ":data/resource_full.pb", - ":data/resource_minimal_good.pb", - ":data/resource_no_name.pb", - ":data/resource_no_numerator.pb", - ":data/resource_no_unit.pb", - ], - deps = [ - "//:gpr", - "//:grpc", - "//test/core/util:gpr_test_util", - "//test/core/util:grpc_test_util", - ], -) - -grpc_cc_test( - name = "trace_context_test", - srcs = ["trace_context_test.c"], - language = "C", - data = [ - ":data/context_empty.pb", - ":data/context_full.pb", - ":data/context_no_span_options.pb", - ":data/context_span_only.pb", - ":data/context_trace_only.pb", - ], - deps = [ - "//:gpr", - "//:grpc", - "//test/core/util:gpr_test_util", - "//test/core/util:grpc_test_util", - ], -) diff --git a/test/core/census/README b/test/core/census/README deleted file mode 100644 index d5363b7233..0000000000 --- a/test/core/census/README +++ /dev/null @@ -1,7 +0,0 @@ -Test source and data files for Census. - -binary proto files (*.pb) in data directory are generated from the *.txt file, -via: - -BASE="filename" -cat $BASE.txt | protoc --encode=google.census.Resource census.proto > $BASE.pb diff --git a/test/core/census/context_test.c b/test/core/census/context_test.c deleted file mode 100644 index ca5a6ec5cd..0000000000 --- a/test/core/census/context_test.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * - * 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. - * - */ - -// Test census_context functions, including encoding/decoding - -#include <grpc/census.h> -#include <grpc/support/log.h> -#include <grpc/support/time.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "test/core/util/test_config.h" - -// A set of tags Used to create a basic context for testing. Note that -// replace_add_delete_test() relies on specific offsets into this array - if -// you add or delete entries, you will also need to change the test. -#define BASIC_TAG_COUNT 8 -static census_tag basic_tags[BASIC_TAG_COUNT] = { - /* 0 */ {"key0", "tag value", 0}, - /* 1 */ {"k1", "a", CENSUS_TAG_PROPAGATE}, - /* 2 */ {"k2", "a longer tag value supercalifragilisticexpialiadocious", - CENSUS_TAG_STATS}, - /* 3 */ {"key_three", "", 0}, - /* 4 */ {"a_really_really_really_really_long_key_4", "random", - CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS}, - /* 5 */ {"k5", "v5", CENSUS_TAG_PROPAGATE}, - /* 6 */ {"k6", "v6", CENSUS_TAG_STATS}, - /* 7 */ {"k7", "v7", CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS}}; - -// Set of tags used to modify the basic context. Note that -// replace_add_delete_test() relies on specific offsets into this array - if -// you add or delete entries, you will also need to change the test. Other -// tests that rely on specific instances have XXX_XXX_OFFSET definitions (also -// change the defines below if you add/delete entires). -#define MODIFY_TAG_COUNT 10 -static census_tag modify_tags[MODIFY_TAG_COUNT] = { -#define REPLACE_VALUE_OFFSET 0 - /* 0 */ {"key0", "replace key0", 0}, // replaces tag value only -#define ADD_TAG_OFFSET 1 - /* 1 */ {"new_key", "xyzzy", CENSUS_TAG_STATS}, // new tag -#define DELETE_TAG_OFFSET 2 - /* 2 */ {"k5", NULL, 0}, // should delete tag - /* 3 */ {"k5", NULL, 0}, // try deleting already-deleted tag - /* 4 */ {"non-existent", NULL, 0}, // delete non-existent tag -#define REPLACE_FLAG_OFFSET 5 - /* 5 */ {"k1", "a", 0}, // change flags only - /* 6 */ {"k7", "bar", CENSUS_TAG_STATS}, // change flags and value - /* 7 */ {"k2", "", CENSUS_TAG_PROPAGATE}, // more value and flags change - /* 8 */ {"k5", "bar", 0}, // add back tag, with different value - /* 9 */ {"foo", "bar", CENSUS_TAG_PROPAGATE}, // another new tag -}; - -// Utility function to compare tags. Returns true if all fields match. -static bool compare_tag(const census_tag *t1, const census_tag *t2) { - return (strcmp(t1->key, t2->key) == 0 && strcmp(t1->value, t2->value) == 0 && - t1->flags == t2->flags); -} - -// Utility function to validate a tag exists in context. -static bool validate_tag(const census_context *context, const census_tag *tag) { - census_tag tag2; - if (census_context_get_tag(context, tag->key, &tag2) != 1) return false; - return compare_tag(tag, &tag2); -} - -// Create an empty context. -static void empty_test(void) { - struct census_context *context = census_context_create(NULL, NULL, 0, NULL); - GPR_ASSERT(context != NULL); - const census_context_status *status = census_context_get_status(context); - census_context_status expected = {0, 0, 0, 0, 0, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); -} - -// Test create and iteration over basic context. -static void basic_test(void) { - const census_context_status *status; - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, &status); - census_context_status expected = {4, 4, 0, 8, 0, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_iterator it; - census_context_initialize_iterator(context, &it); - census_tag tag; - while (census_context_next_tag(&it, &tag)) { - // can't rely on tag return order: make sure it matches exactly one. - int matches = 0; - for (int i = 0; i < BASIC_TAG_COUNT; i++) { - if (compare_tag(&tag, &basic_tags[i])) matches++; - } - GPR_ASSERT(matches == 1); - } - census_context_destroy(context); -} - -// Test census_context_get_tag(). -static void lookup_by_key_test(void) { - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - census_tag tag; - for (int i = 0; i < BASIC_TAG_COUNT; i++) { - GPR_ASSERT(census_context_get_tag(context, basic_tags[i].key, &tag) == 1); - GPR_ASSERT(compare_tag(&tag, &basic_tags[i])); - } - // non-existent keys - GPR_ASSERT(census_context_get_tag(context, "key", &tag) == 0); - GPR_ASSERT(census_context_get_tag(context, "key01", &tag) == 0); - GPR_ASSERT(census_context_get_tag(context, "k9", &tag) == 0); - GPR_ASSERT(census_context_get_tag(context, "random", &tag) == 0); - GPR_ASSERT(census_context_get_tag(context, "", &tag) == 0); - census_context_destroy(context); -} - -// Try creating context with invalid entries. -static void invalid_test(void) { - char key[300]; - memset(key, 'k', 299); - key[299] = 0; - char value[300]; - memset(value, 'v', 299); - value[299] = 0; - census_tag tag = {key, value, 0}; - // long keys, short value. Key lengths (including terminator) should be - // <= 255 (CENSUS_MAX_TAG_KV_LEN) - value[3] = 0; - GPR_ASSERT(strlen(value) == 3); - GPR_ASSERT(strlen(key) == 299); - const census_context_status *status; - struct census_context *context = - census_context_create(NULL, &tag, 1, &status); - census_context_status expected = {0, 0, 0, 0, 0, 1, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); - key[CENSUS_MAX_TAG_KV_LEN] = 0; - GPR_ASSERT(strlen(key) == CENSUS_MAX_TAG_KV_LEN); - context = census_context_create(NULL, &tag, 1, &status); - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); - key[CENSUS_MAX_TAG_KV_LEN - 1] = 0; - GPR_ASSERT(strlen(key) == CENSUS_MAX_TAG_KV_LEN - 1); - context = census_context_create(NULL, &tag, 1, &status); - census_context_status expected2 = {0, 1, 0, 1, 0, 0, 0}; - GPR_ASSERT(memcmp(status, &expected2, sizeof(expected2)) == 0); - census_context_destroy(context); - // now try with long values - value[3] = 'v'; - GPR_ASSERT(strlen(value) == 299); - context = census_context_create(NULL, &tag, 1, &status); - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); - value[CENSUS_MAX_TAG_KV_LEN] = 0; - GPR_ASSERT(strlen(value) == CENSUS_MAX_TAG_KV_LEN); - context = census_context_create(NULL, &tag, 1, &status); - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); - value[CENSUS_MAX_TAG_KV_LEN - 1] = 0; - GPR_ASSERT(strlen(value) == CENSUS_MAX_TAG_KV_LEN - 1); - context = census_context_create(NULL, &tag, 1, &status); - GPR_ASSERT(memcmp(status, &expected2, sizeof(expected2)) == 0); - census_context_destroy(context); - // 0 length key. - key[0] = 0; - GPR_ASSERT(strlen(key) == 0); - context = census_context_create(NULL, &tag, 1, &status); - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); - // invalid key character - key[0] = 31; // 32 (' ') is the first valid character value - key[1] = 0; - GPR_ASSERT(strlen(key) == 1); - context = census_context_create(NULL, &tag, 1, &status); - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); - // invalid value character - key[0] = ' '; - value[5] = 127; // 127 (DEL) is ('~' + 1) - value[8] = 0; - GPR_ASSERT(strlen(key) == 1); - GPR_ASSERT(strlen(value) == 8); - context = census_context_create(NULL, &tag, 1, &status); - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); -} - -// Make a copy of a context -static void copy_test(void) { - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - const census_context_status *status; - struct census_context *context2 = - census_context_create(context, NULL, 0, &status); - census_context_status expected = {4, 4, 0, 0, 0, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - for (int i = 0; i < BASIC_TAG_COUNT; i++) { - census_tag tag; - GPR_ASSERT(census_context_get_tag(context2, basic_tags[i].key, &tag) == 1); - GPR_ASSERT(compare_tag(&tag, &basic_tags[i])); - } - census_context_destroy(context); - census_context_destroy(context2); -} - -// replace a single tag value -static void replace_value_test(void) { - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - const census_context_status *status; - struct census_context *context2 = census_context_create( - context, modify_tags + REPLACE_VALUE_OFFSET, 1, &status); - census_context_status expected = {4, 4, 0, 0, 1, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_tag tag; - GPR_ASSERT(census_context_get_tag( - context2, modify_tags[REPLACE_VALUE_OFFSET].key, &tag) == 1); - GPR_ASSERT(compare_tag(&tag, &modify_tags[REPLACE_VALUE_OFFSET])); - census_context_destroy(context); - census_context_destroy(context2); -} - -// replace a single tags flags -static void replace_flags_test(void) { - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - const census_context_status *status; - struct census_context *context2 = census_context_create( - context, modify_tags + REPLACE_FLAG_OFFSET, 1, &status); - census_context_status expected = {3, 5, 0, 0, 1, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_tag tag; - GPR_ASSERT(census_context_get_tag( - context2, modify_tags[REPLACE_FLAG_OFFSET].key, &tag) == 1); - GPR_ASSERT(compare_tag(&tag, &modify_tags[REPLACE_FLAG_OFFSET])); - census_context_destroy(context); - census_context_destroy(context2); -} - -// delete a single tag. -static void delete_tag_test(void) { - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - const census_context_status *status; - struct census_context *context2 = census_context_create( - context, modify_tags + DELETE_TAG_OFFSET, 1, &status); - census_context_status expected = {3, 4, 1, 0, 0, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_tag tag; - GPR_ASSERT(census_context_get_tag( - context2, modify_tags[DELETE_TAG_OFFSET].key, &tag) == 0); - census_context_destroy(context); - census_context_destroy(context2); -} - -// add a single new tag. -static void add_tag_test(void) { - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - const census_context_status *status; - struct census_context *context2 = - census_context_create(context, modify_tags + ADD_TAG_OFFSET, 1, &status); - census_context_status expected = {4, 5, 0, 1, 0, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_tag tag; - GPR_ASSERT(census_context_get_tag(context2, modify_tags[ADD_TAG_OFFSET].key, - &tag) == 1); - GPR_ASSERT(compare_tag(&tag, &modify_tags[ADD_TAG_OFFSET])); - census_context_destroy(context); - census_context_destroy(context2); -} - -// test many changes at once. -static void replace_add_delete_test(void) { - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - const census_context_status *status; - struct census_context *context2 = - census_context_create(context, modify_tags, MODIFY_TAG_COUNT, &status); - census_context_status expected = {3, 7, 1, 3, 4, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - // validate context contents. Use specific indices into the two arrays - // holding tag values. - GPR_ASSERT(validate_tag(context2, &basic_tags[3])); - GPR_ASSERT(validate_tag(context2, &basic_tags[4])); - GPR_ASSERT(validate_tag(context2, &basic_tags[6])); - GPR_ASSERT(validate_tag(context2, &modify_tags[0])); - GPR_ASSERT(validate_tag(context2, &modify_tags[1])); - GPR_ASSERT(validate_tag(context2, &modify_tags[5])); - GPR_ASSERT(validate_tag(context2, &modify_tags[6])); - GPR_ASSERT(validate_tag(context2, &modify_tags[7])); - GPR_ASSERT(validate_tag(context2, &modify_tags[8])); - GPR_ASSERT(validate_tag(context2, &modify_tags[9])); - GPR_ASSERT(!validate_tag(context2, &basic_tags[0])); - GPR_ASSERT(!validate_tag(context2, &basic_tags[1])); - GPR_ASSERT(!validate_tag(context2, &basic_tags[2])); - GPR_ASSERT(!validate_tag(context2, &basic_tags[5])); - GPR_ASSERT(!validate_tag(context2, &basic_tags[7])); - census_context_destroy(context); - census_context_destroy(context2); -} - -#define BUF_SIZE 200 - -// test encode/decode. -static void encode_decode_test(void) { - char buffer[BUF_SIZE]; - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - // Test with too small a buffer - GPR_ASSERT(census_context_encode(context, buffer, 2) == 0); - // Test with sufficient buffer - size_t buf_used = census_context_encode(context, buffer, BUF_SIZE); - GPR_ASSERT(buf_used != 0); - census_context *context2 = census_context_decode(buffer, buf_used); - GPR_ASSERT(context2 != NULL); - const census_context_status *status = census_context_get_status(context2); - census_context_status expected = {4, 0, 0, 0, 0, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - for (int i = 0; i < BASIC_TAG_COUNT; i++) { - census_tag tag; - if (CENSUS_TAG_IS_PROPAGATED(basic_tags[i].flags)) { - GPR_ASSERT(census_context_get_tag(context2, basic_tags[i].key, &tag) == - 1); - GPR_ASSERT(compare_tag(&tag, &basic_tags[i])); - } else { - GPR_ASSERT(census_context_get_tag(context2, basic_tags[i].key, &tag) == - 0); - } - } - census_context_destroy(context2); - census_context_destroy(context); -} - -int main(int argc, char *argv[]) { - grpc_test_init(argc, argv); - empty_test(); - basic_test(); - lookup_by_key_test(); - invalid_test(); - copy_test(); - replace_value_test(); - replace_flags_test(); - delete_tag_test(); - add_tag_test(); - replace_add_delete_test(); - encode_decode_test(); - return 0; -} diff --git a/test/core/census/data/context_empty.pb b/test/core/census/data/context_empty.pb deleted file mode 100644 index e69de29bb2..0000000000 --- a/test/core/census/data/context_empty.pb +++ /dev/null diff --git a/test/core/census/data/context_empty.txt b/test/core/census/data/context_empty.txt deleted file mode 100644 index e69de29bb2..0000000000 --- a/test/core/census/data/context_empty.txt +++ /dev/null diff --git a/test/core/census/data/context_full.pb b/test/core/census/data/context_full.pb Binary files differdeleted file mode 100644 index 7b5895cbf1..0000000000 --- a/test/core/census/data/context_full.pb +++ /dev/null diff --git a/test/core/census/data/context_full.txt b/test/core/census/data/context_full.txt deleted file mode 100644 index 7d8df37ea1..0000000000 --- a/test/core/census/data/context_full.txt +++ /dev/null @@ -1,4 +0,0 @@ -trace_id_hi : 5 -trace_id_lo : 1 -span_id : 7 -span_options : 1 diff --git a/test/core/census/data/context_no_span_options.pb b/test/core/census/data/context_no_span_options.pb Binary files differdeleted file mode 100644 index 4b3425ac01..0000000000 --- a/test/core/census/data/context_no_span_options.pb +++ /dev/null diff --git a/test/core/census/data/context_no_span_options.txt b/test/core/census/data/context_no_span_options.txt deleted file mode 100644 index 4c8398ffd0..0000000000 --- a/test/core/census/data/context_no_span_options.txt +++ /dev/null @@ -1,3 +0,0 @@ -trace_id_hi : 5 -trace_id_lo : 1 -span_id : 7 diff --git a/test/core/census/data/context_span_only.pb b/test/core/census/data/context_span_only.pb Binary files differdeleted file mode 100644 index a9315be91a..0000000000 --- a/test/core/census/data/context_span_only.pb +++ /dev/null diff --git a/test/core/census/data/context_span_only.txt b/test/core/census/data/context_span_only.txt deleted file mode 100644 index 4e473fce53..0000000000 --- a/test/core/census/data/context_span_only.txt +++ /dev/null @@ -1,2 +0,0 @@ -span_id : 7 -span_options : 1 diff --git a/test/core/census/data/context_trace_only.pb b/test/core/census/data/context_trace_only.pb Binary files differdeleted file mode 100644 index aabb325f92..0000000000 --- a/test/core/census/data/context_trace_only.pb +++ /dev/null diff --git a/test/core/census/data/context_trace_only.txt b/test/core/census/data/context_trace_only.txt deleted file mode 100644 index e48a6d7457..0000000000 --- a/test/core/census/data/context_trace_only.txt +++ /dev/null @@ -1,3 +0,0 @@ -trace_id_hi : 5 -trace_id_lo : 1 -span_options : 1 diff --git a/test/core/census/data/resource_empty_name.pb b/test/core/census/data/resource_empty_name.pb deleted file mode 100644 index 4d547445fa..0000000000 --- a/test/core/census/data/resource_empty_name.pb +++ /dev/null @@ -1 +0,0 @@ -
\ No newline at end of file diff --git a/test/core/census/data/resource_empty_name.txt b/test/core/census/data/resource_empty_name.txt deleted file mode 100644 index 271fd3274c..0000000000 --- a/test/core/census/data/resource_empty_name.txt +++ /dev/null @@ -1,5 +0,0 @@ -# Name is present, but empty. -name : '' -unit { - numerator : SECS -} diff --git a/test/core/census/data/resource_full.pb b/test/core/census/data/resource_full.pb deleted file mode 100644 index e4c6a2aef5..0000000000 --- a/test/core/census/data/resource_full.pb +++ /dev/null @@ -1,2 +0,0 @@ - -
full_resource"A resource with everything defined
\ No newline at end of file diff --git a/test/core/census/data/resource_full.txt b/test/core/census/data/resource_full.txt deleted file mode 100644 index 1aa2fafe3a..0000000000 --- a/test/core/census/data/resource_full.txt +++ /dev/null @@ -1,9 +0,0 @@ -# A full resource definition - all fields filled out. -name : 'full_resource' -description : 'A resource with everything defined' -unit { - # Megabits per second. - prefix : 6 - numerator : BITS - denominator : SECS -} diff --git a/test/core/census/data/resource_minimal_good.pb b/test/core/census/data/resource_minimal_good.pb deleted file mode 100644 index 7100c462bf..0000000000 --- a/test/core/census/data/resource_minimal_good.pb +++ /dev/null @@ -1,2 +0,0 @@ - -minimal_good
\ No newline at end of file diff --git a/test/core/census/data/resource_minimal_good.txt b/test/core/census/data/resource_minimal_good.txt deleted file mode 100644 index a7a7e71dd6..0000000000 --- a/test/core/census/data/resource_minimal_good.txt +++ /dev/null @@ -1,5 +0,0 @@ -# A minimal "good" Resource definition: has a name and numerator/unit. -name : 'minimal_good' -unit { - numerator : SECS -} diff --git a/test/core/census/data/resource_no_name.pb b/test/core/census/data/resource_no_name.pb deleted file mode 100644 index 4d547445fa..0000000000 --- a/test/core/census/data/resource_no_name.pb +++ /dev/null @@ -1 +0,0 @@ -
\ No newline at end of file diff --git a/test/core/census/data/resource_no_name.txt b/test/core/census/data/resource_no_name.txt deleted file mode 100644 index 8f12a91d35..0000000000 --- a/test/core/census/data/resource_no_name.txt +++ /dev/null @@ -1,4 +0,0 @@ -# The minimal good Resource without a name. -unit { - numerator : SECS -} diff --git a/test/core/census/data/resource_no_numerator.pb b/test/core/census/data/resource_no_numerator.pb deleted file mode 100644 index 2a5cceee70..0000000000 --- a/test/core/census/data/resource_no_numerator.pb +++ /dev/null @@ -1,2 +0,0 @@ - -resource_no_numeratorýÿÿÿÿÿÿÿÿ
\ No newline at end of file diff --git a/test/core/census/data/resource_no_numerator.txt b/test/core/census/data/resource_no_numerator.txt deleted file mode 100644 index fc1fec74a2..0000000000 --- a/test/core/census/data/resource_no_numerator.txt +++ /dev/null @@ -1,6 +0,0 @@ -# Resource without a numerator -name : 'resource_no_numerator' -unit { - prefix : -3 - denominator : SECS -} diff --git a/test/core/census/data/resource_no_unit.pb b/test/core/census/data/resource_no_unit.pb deleted file mode 100644 index 9dca2620e0..0000000000 --- a/test/core/census/data/resource_no_unit.pb +++ /dev/null @@ -1,2 +0,0 @@ - -resource_no_unit
\ No newline at end of file diff --git a/test/core/census/data/resource_no_unit.txt b/test/core/census/data/resource_no_unit.txt deleted file mode 100644 index c5d5115ceb..0000000000 --- a/test/core/census/data/resource_no_unit.txt +++ /dev/null @@ -1,2 +0,0 @@ -# The minimal good resource without a unit -name : 'resource_no_unit' diff --git a/test/core/census/intrusive_hash_map_test.c b/test/core/census/intrusive_hash_map_test.c deleted file mode 100644 index 0826b55c63..0000000000 --- a/test/core/census/intrusive_hash_map_test.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * - * Copyright 2017 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/ext/census/intrusive_hash_map.h" - -#include <grpc/support/log.h> -#include <grpc/support/useful.h> -#include "test/core/util/test_config.h" - -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* The initial size of an intrusive hash map will be 2 to this power. */ -static const uint32_t kInitialLog2Size = 4; - -/* Simple object used for testing intrusive_hash_map. */ -typedef struct object { uint64_t val; } object; - -/* Helper function to allocate and initialize object. */ -static __inline object *make_new_object(uint64_t val) { - object *obj = (object *)gpr_malloc(sizeof(object)); - obj->val = val; - return obj; -} - -/* Wrapper struct for object. */ -typedef struct ptr_item { - INTRUSIVE_HASH_MAP_HEADER; - object *obj; -} ptr_item; - -/* Helper function that creates a new hash map item. It is up to the user to - * free the item that was allocated. */ -static __inline ptr_item *make_ptr_item(uint64_t key, uint64_t value) { - ptr_item *new_item = (ptr_item *)gpr_malloc(sizeof(ptr_item)); - new_item->IHM_key = key; - new_item->IHM_hash_link = NULL; - new_item->obj = make_new_object(value); - return new_item; -} - -/* Helper function to deallocate ptr_item. */ -static void free_ptr_item(void *ptr) { gpr_free(((ptr_item *)ptr)->obj); } - -/* Simple string object used for testing intrusive_hash_map. */ -typedef struct string_item { - INTRUSIVE_HASH_MAP_HEADER; - // User data. - char buf[32]; - uint16_t len; -} string_item; - -/* Helper function to allocate and initialize string object. */ -static string_item *make_string_item(uint64_t key, const char *buf, - uint16_t len) { - string_item *item = (string_item *)gpr_malloc(sizeof(string_item)); - item->IHM_key = key; - item->IHM_hash_link = NULL; - item->len = len; - memcpy(item->buf, buf, sizeof(char) * len); - return item; -} - -/* Helper function for comparing two string objects. */ -static bool compare_string_item(const string_item *A, const string_item *B) { - if (A->IHM_key != B->IHM_key || A->len != B->len) - return false; - else { - for (int i = 0; i < A->len; ++i) { - if (A->buf[i] != B->buf[i]) return false; - } - } - - return true; -} - -void test_empty() { - intrusive_hash_map hash_map; - intrusive_hash_map_init(&hash_map, kInitialLog2Size); - GPR_ASSERT(0 == intrusive_hash_map_size(&hash_map)); - GPR_ASSERT(intrusive_hash_map_empty(&hash_map)); - intrusive_hash_map_free(&hash_map, NULL); -} - -void test_single_item() { - intrusive_hash_map hash_map; - intrusive_hash_map_init(&hash_map, kInitialLog2Size); - - ptr_item *new_item = make_ptr_item(10, 20); - bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item); - GPR_ASSERT(ok); - - ptr_item *item1 = - (ptr_item *)intrusive_hash_map_find(&hash_map, (uint64_t)10); - GPR_ASSERT(item1->obj->val == 20); - GPR_ASSERT(item1 == new_item); - - ptr_item *item2 = - (ptr_item *)intrusive_hash_map_erase(&hash_map, (uint64_t)10); - GPR_ASSERT(item2 == new_item); - - gpr_free(new_item->obj); - gpr_free(new_item); - GPR_ASSERT(0 == intrusive_hash_map_size(&hash_map)); - intrusive_hash_map_free(&hash_map, &free_ptr_item); -} - -void test_two_items() { - intrusive_hash_map hash_map; - intrusive_hash_map_init(&hash_map, kInitialLog2Size); - - string_item *new_item1 = make_string_item(10, "test1", 5); - bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item1); - GPR_ASSERT(ok); - string_item *new_item2 = make_string_item(20, "test2", 5); - ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item2); - GPR_ASSERT(ok); - - string_item *item1 = - (string_item *)intrusive_hash_map_find(&hash_map, (uint64_t)10); - GPR_ASSERT(compare_string_item(new_item1, item1)); - GPR_ASSERT(item1 == new_item1); - string_item *item2 = - (string_item *)intrusive_hash_map_find(&hash_map, (uint64_t)20); - GPR_ASSERT(compare_string_item(new_item2, item2)); - GPR_ASSERT(item2 == new_item2); - - item1 = (string_item *)intrusive_hash_map_erase(&hash_map, (uint64_t)10); - GPR_ASSERT(item1 == new_item1); - item2 = (string_item *)intrusive_hash_map_erase(&hash_map, (uint64_t)20); - GPR_ASSERT(item2 == new_item2); - - gpr_free(new_item1); - gpr_free(new_item2); - GPR_ASSERT(0 == intrusive_hash_map_size(&hash_map)); - intrusive_hash_map_free(&hash_map, NULL); -} - -// Test resetting and clearing the hash map. -void test_reset_clear() { - intrusive_hash_map hash_map; - intrusive_hash_map_init(&hash_map, kInitialLog2Size); - - // Add some data to the hash_map. - for (uint64_t i = 0; i < 3; ++i) { - intrusive_hash_map_insert(&hash_map, (hm_item *)make_ptr_item(i, i)); - } - GPR_ASSERT(3 == intrusive_hash_map_size(&hash_map)); - - // Test find. - for (uint64_t i = 0; i < 3; ++i) { - ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, i); - GPR_ASSERT(item != NULL); - GPR_ASSERT(item->IHM_key == i && item->obj->val == i); - } - - intrusive_hash_map_clear(&hash_map, &free_ptr_item); - GPR_ASSERT(intrusive_hash_map_empty(&hash_map)); - intrusive_hash_map_free(&hash_map, &free_ptr_item); -} - -// Check that the hash_map contains every key between [min_value, max_value] -// (inclusive). -void check_hash_map_values(intrusive_hash_map *hash_map, uint64_t min_value, - uint64_t max_value) { - GPR_ASSERT(intrusive_hash_map_size(hash_map) == max_value - min_value + 1); - - for (uint64_t i = min_value; i <= max_value; ++i) { - ptr_item *item = (ptr_item *)intrusive_hash_map_find(hash_map, i); - GPR_ASSERT(item != NULL); - GPR_ASSERT(item->obj->val == i); - } -} - -// Add many items and cause the hash_map to extend. -void test_extend() { - intrusive_hash_map hash_map; - intrusive_hash_map_init(&hash_map, kInitialLog2Size); - - const uint64_t kNumValues = (1 << 16); - - for (uint64_t i = 0; i < kNumValues; ++i) { - ptr_item *item = make_ptr_item(i, i); - bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)item); - GPR_ASSERT(ok); - if (i % 1000 == 0) { - check_hash_map_values(&hash_map, 0, i); - } - } - - for (uint64_t i = 0; i < kNumValues; ++i) { - ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, i); - GPR_ASSERT(item != NULL); - GPR_ASSERT(item->IHM_key == i && item->obj->val == i); - ptr_item *item2 = (ptr_item *)intrusive_hash_map_erase(&hash_map, i); - GPR_ASSERT(item == item2); - gpr_free(item->obj); - gpr_free(item); - } - - GPR_ASSERT(intrusive_hash_map_empty(&hash_map)); - intrusive_hash_map_free(&hash_map, &free_ptr_item); -} - -void test_stress() { - intrusive_hash_map hash_map; - intrusive_hash_map_init(&hash_map, kInitialLog2Size); - size_t n = 0; - - // Randomly add and insert entries 1000000 times. - for (uint64_t i = 0; i < 1000000; ++i) { - int op = rand() & 0x1; - - switch (op) { - // Case 0 is insertion of entry. - case 0: { - uint64_t key = (uint64_t)(rand() % 10000); - ptr_item *item = make_ptr_item(key, key); - bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)item); - if (ok) { - n++; - } else { - gpr_free(item->obj); - gpr_free(item); - } - break; - } - // Case 1 is removal of entry. - case 1: { - uint64_t key = (uint64_t)(rand() % 10000); - ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, key); - if (item != NULL) { - n--; - GPR_ASSERT(key == item->obj->val); - ptr_item *item2 = - (ptr_item *)intrusive_hash_map_erase(&hash_map, key); - GPR_ASSERT(item == item2); - gpr_free(item->obj); - gpr_free(item); - } - break; - } - } - } - // Check size - GPR_ASSERT(n == intrusive_hash_map_size(&hash_map)); - - // Clean the hash_map up. - intrusive_hash_map_clear(&hash_map, &free_ptr_item); - GPR_ASSERT(intrusive_hash_map_empty(&hash_map)); - intrusive_hash_map_free(&hash_map, &free_ptr_item); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - gpr_time_init(); - srand((unsigned)gpr_now(GPR_CLOCK_REALTIME).tv_nsec); - - test_empty(); - test_single_item(); - test_two_items(); - test_reset_clear(); - test_extend(); - test_stress(); - - return 0; -} diff --git a/test/core/census/mlog_test.c b/test/core/census/mlog_test.c deleted file mode 100644 index 968fd91da4..0000000000 --- a/test/core/census/mlog_test.c +++ /dev/null @@ -1,574 +0,0 @@ -/* - * - * 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/ext/census/mlog.h" -#include <grpc/support/cpu.h> -#include <grpc/support/log.h> -#include <grpc/support/port_platform.h> -#include <grpc/support/sync.h> -#include <grpc/support/thd.h> -#include <grpc/support/time.h> -#include <grpc/support/useful.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "test/core/util/test_config.h" - -// Change this to non-zero if you want more output. -#define VERBOSE 0 - -// Log size to use for all tests. -#define LOG_SIZE_IN_MB 1 -#define LOG_SIZE_IN_BYTES (LOG_SIZE_IN_MB << 20) - -// Fills in 'record' of size 'size'. Each byte in record is filled in with the -// same value. The value is extracted from 'record' pointer. -static void write_record(char* record, size_t size) { - char data = (char)((uintptr_t)record % 255); - memset(record, data, size); -} - -// Reads fixed size records. Returns the number of records read in -// 'num_records'. -static void read_records(size_t record_size, const char* buffer, - size_t buffer_size, int* num_records) { - GPR_ASSERT(buffer_size >= record_size); - GPR_ASSERT(buffer_size % record_size == 0); - *num_records = (int)(buffer_size / record_size); - for (int i = 0; i < *num_records; ++i) { - const char* record = buffer + (record_size * (size_t)i); - char data = (char)((uintptr_t)record % 255); - for (size_t j = 0; j < record_size; ++j) { - GPR_ASSERT(data == record[j]); - } - } -} - -// Tries to write the specified number of records. Stops when the log gets -// full. Returns the number of records written. Spins for random -// number of times, up to 'max_spin_count', between writes. -static int write_records_to_log(int writer_id, size_t record_size, - int num_records, int max_spin_count) { - int counter = 0; - for (int i = 0; i < num_records; ++i) { - int spin_count = max_spin_count ? rand() % max_spin_count : 0; - if (VERBOSE && (counter++ == num_records / 10)) { - printf(" Writer %d: %d out of %d written\n", writer_id, i, num_records); - counter = 0; - } - char* record = (char*)(census_log_start_write(record_size)); - if (record == NULL) { - return i; - } - write_record(record, record_size); - census_log_end_write(record, record_size); - for (int j = 0; j < spin_count; ++j) { - GPR_ASSERT(j >= 0); - } - } - return num_records; -} - -// Performs a single read iteration. Returns the number of records read. -static int perform_read_iteration(size_t record_size) { - const void* read_buffer = NULL; - size_t bytes_available; - int records_read = 0; - census_log_init_reader(); - while ((read_buffer = census_log_read_next(&bytes_available))) { - int num_records = 0; - read_records(record_size, (const char*)read_buffer, bytes_available, - &num_records); - records_read += num_records; - } - return records_read; -} - -// Asserts that the log is empty. -static void assert_log_empty(void) { - census_log_init_reader(); - size_t bytes_available; - GPR_ASSERT(census_log_read_next(&bytes_available) == NULL); -} - -// Fills the log and verifies data. If 'no fragmentation' is true, records -// are sized such that CENSUS_LOG_2_MAX_RECORD_SIZE is a multiple of record -// size. If not a circular log, verifies that the number of records written -// match the number of records read. -static void fill_log(size_t log_size, int no_fragmentation, int circular_log) { - size_t size; - if (no_fragmentation) { - int log2size = rand() % (CENSUS_LOG_2_MAX_RECORD_SIZE + 1); - size = ((size_t)1 << log2size); - } else { - while (1) { - size = 1 + ((size_t)rand() % CENSUS_LOG_MAX_RECORD_SIZE); - if (CENSUS_LOG_MAX_RECORD_SIZE % size) { - break; - } - } - } - int records_written = - write_records_to_log(0 /* writer id */, size, - (int)((log_size / size) * 2), 0 /* spin count */); - int records_read = perform_read_iteration(size); - if (!circular_log) { - GPR_ASSERT(records_written == records_read); - } - assert_log_empty(); -} - -// Structure to pass args to writer_thread -typedef struct writer_thread_args { - // Index of this thread in the writers vector. - int index; - // Record size. - size_t record_size; - // Number of records to write. - int num_records; - // Used to signal when writer is complete - gpr_cv* done; - gpr_mu* mu; - int* count; -} writer_thread_args; - -// Writes the given number of records of random size (up to kMaxRecordSize) and -// random data to the specified log. -static void writer_thread(void* arg) { - writer_thread_args* args = (writer_thread_args*)arg; - // Maximum number of times to spin between writes. - static const int MAX_SPIN_COUNT = 50; - int records_written = 0; - if (VERBOSE) { - printf(" Writer %d starting\n", args->index); - } - while (records_written < args->num_records) { - records_written += write_records_to_log(args->index, args->record_size, - args->num_records - records_written, - MAX_SPIN_COUNT); - if (records_written < args->num_records) { - // Ran out of log space. Sleep for a bit and let the reader catch up. - // This should never happen for circular logs. - if (VERBOSE) { - printf( - " Writer %d stalled due to out-of-space: %d out of %d " - "written\n", - args->index, records_written, args->num_records); - } - gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(10)); - } - } - // Done. Decrement count and signal. - gpr_mu_lock(args->mu); - (*args->count)--; - gpr_cv_signal(args->done); - if (VERBOSE) { - printf(" Writer %d done\n", args->index); - } - gpr_mu_unlock(args->mu); -} - -// struct to pass args to reader_thread -typedef struct reader_thread_args { - // Record size. - size_t record_size; - // Interval between read iterations. - int read_iteration_interval_in_msec; - // Total number of records. - int total_records; - // Signalled when reader should stop. - gpr_cv stop; - int stop_flag; - // Used to signal when reader has finished - gpr_cv* done; - gpr_mu* mu; - int running; -} reader_thread_args; - -// Reads and verifies the specified number of records. Reader can also be -// stopped via gpr_cv_signal(&args->stop). Sleeps for 'read_interval_in_msec' -// between read iterations. -static void reader_thread(void* arg) { - reader_thread_args* args = (reader_thread_args*)arg; - if (VERBOSE) { - printf(" Reader starting\n"); - } - gpr_timespec interval = gpr_time_from_micros( - args->read_iteration_interval_in_msec * 1000, GPR_TIMESPAN); - gpr_mu_lock(args->mu); - int records_read = 0; - int num_iterations = 0; - int counter = 0; - while (!args->stop_flag && records_read < args->total_records) { - gpr_cv_wait(&args->stop, args->mu, interval); - if (!args->stop_flag) { - records_read += perform_read_iteration(args->record_size); - GPR_ASSERT(records_read <= args->total_records); - if (VERBOSE && (counter++ == 100000)) { - printf(" Reader: %d out of %d read\n", records_read, - args->total_records); - counter = 0; - } - ++num_iterations; - } - } - // Done - args->running = 0; - gpr_cv_signal(args->done); - if (VERBOSE) { - printf(" Reader: records: %d, iterations: %d\n", records_read, - num_iterations); - } - gpr_mu_unlock(args->mu); -} - -// Creates NUM_WRITERS writers where each writer writes NUM_RECORDS_PER_WRITER -// records. Also, starts a reader that iterates over and reads blocks every -// READ_ITERATION_INTERVAL_IN_MSEC. -// Number of writers. -#define NUM_WRITERS 5 -static void multiple_writers_single_reader(int circular_log) { - // Sleep interval between read iterations. - static const int READ_ITERATION_INTERVAL_IN_MSEC = 10; - // Maximum record size. - static const size_t MAX_RECORD_SIZE = 20; - // Number of records written by each writer. This is sized such that we - // will write through the entire log ~10 times. - const int NUM_RECORDS_PER_WRITER = - (int)((10 * census_log_remaining_space()) / (MAX_RECORD_SIZE / 2)) / - NUM_WRITERS; - size_t record_size = ((size_t)rand() % MAX_RECORD_SIZE) + 1; - // Create and start writers. - writer_thread_args writers[NUM_WRITERS]; - int writers_count = NUM_WRITERS; - gpr_cv writers_done; - gpr_mu writers_mu; // protects writers_done and writers_count - gpr_cv_init(&writers_done); - gpr_mu_init(&writers_mu); - gpr_thd_id id; - for (int i = 0; i < NUM_WRITERS; ++i) { - writers[i].index = i; - writers[i].record_size = record_size; - writers[i].num_records = NUM_RECORDS_PER_WRITER; - writers[i].done = &writers_done; - writers[i].count = &writers_count; - writers[i].mu = &writers_mu; - gpr_thd_new(&id, &writer_thread, &writers[i], NULL); - } - // Start reader. - gpr_cv reader_done; - gpr_mu reader_mu; // protects reader_done and reader.running - reader_thread_args reader; - reader.record_size = record_size; - reader.read_iteration_interval_in_msec = READ_ITERATION_INTERVAL_IN_MSEC; - reader.total_records = NUM_WRITERS * NUM_RECORDS_PER_WRITER; - reader.stop_flag = 0; - gpr_cv_init(&reader.stop); - gpr_cv_init(&reader_done); - reader.done = &reader_done; - gpr_mu_init(&reader_mu); - reader.mu = &reader_mu; - reader.running = 1; - gpr_thd_new(&id, &reader_thread, &reader, NULL); - // Wait for writers to finish. - gpr_mu_lock(&writers_mu); - while (writers_count != 0) { - gpr_cv_wait(&writers_done, &writers_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - gpr_mu_unlock(&writers_mu); - gpr_mu_destroy(&writers_mu); - gpr_cv_destroy(&writers_done); - gpr_mu_lock(&reader_mu); - if (circular_log) { - // Stop reader. - reader.stop_flag = 1; - gpr_cv_signal(&reader.stop); - } - // wait for reader to finish - while (reader.running) { - gpr_cv_wait(&reader_done, &reader_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - if (circular_log) { - // Assert that there were no out-of-space errors. - GPR_ASSERT(0 == census_log_out_of_space_count()); - } - gpr_mu_unlock(&reader_mu); - gpr_mu_destroy(&reader_mu); - gpr_cv_destroy(&reader_done); - if (VERBOSE) { - printf(" Reader: finished\n"); - } -} - -static void setup_test(int circular_log) { - census_log_initialize(LOG_SIZE_IN_MB, circular_log); - // GPR_ASSERT(census_log_remaining_space() == LOG_SIZE_IN_BYTES); -} - -// Attempts to create a record of invalid size (size > -// CENSUS_LOG_MAX_RECORD_SIZE). -void test_invalid_record_size(void) { - static const size_t INVALID_SIZE = CENSUS_LOG_MAX_RECORD_SIZE + 1; - static const size_t VALID_SIZE = 1; - printf("Starting test: invalid record size\n"); - setup_test(0); - void* record = census_log_start_write(INVALID_SIZE); - GPR_ASSERT(record == NULL); - // Now try writing a valid record. - record = census_log_start_write(VALID_SIZE); - GPR_ASSERT(record != NULL); - census_log_end_write(record, VALID_SIZE); - // Verifies that available space went down by one block. In theory, this - // check can fail if the thread is context switched to a new CPU during the - // start_write execution (multiple blocks get allocated), but this has not - // been observed in practice. - // GPR_ASSERT(LOG_SIZE_IN_BYTES - CENSUS_LOG_MAX_RECORD_SIZE == - // census_log_remaining_space()); - census_log_shutdown(); -} - -// Tests end_write() with a different size than what was specified in -// start_write(). -void test_end_write_with_different_size(void) { - static const size_t START_WRITE_SIZE = 10; - static const size_t END_WRITE_SIZE = 7; - printf("Starting test: end write with different size\n"); - setup_test(0); - void* record_written = census_log_start_write(START_WRITE_SIZE); - GPR_ASSERT(record_written != NULL); - census_log_end_write(record_written, END_WRITE_SIZE); - census_log_init_reader(); - size_t bytes_available; - const void* record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_written == record_read); - GPR_ASSERT(END_WRITE_SIZE == bytes_available); - assert_log_empty(); - census_log_shutdown(); -} - -// Verifies that pending records are not available via read_next(). -void test_read_pending_record(void) { - static const size_t PR_RECORD_SIZE = 1024; - printf("Starting test: read pending record\n"); - setup_test(0); - // Start a write. - void* record_written = census_log_start_write(PR_RECORD_SIZE); - GPR_ASSERT(record_written != NULL); - // As write is pending, read should fail. - census_log_init_reader(); - size_t bytes_available; - const void* record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_read == NULL); - // A read followed by end_write() should succeed. - census_log_end_write(record_written, PR_RECORD_SIZE); - census_log_init_reader(); - record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_written == record_read); - GPR_ASSERT(PR_RECORD_SIZE == bytes_available); - assert_log_empty(); - census_log_shutdown(); -} - -// Tries reading beyond pending write. -void test_read_beyond_pending_record(void) { - printf("Starting test: read beyond pending record\n"); - setup_test(0); - // Start a write. - const size_t incomplete_record_size = 10; - void* incomplete_record = census_log_start_write(incomplete_record_size); - GPR_ASSERT(incomplete_record != NULL); - const size_t complete_record_size = 20; - void* complete_record = census_log_start_write(complete_record_size); - GPR_ASSERT(complete_record != NULL); - GPR_ASSERT(complete_record != incomplete_record); - census_log_end_write(complete_record, complete_record_size); - // Now iterate over blocks to read completed records. - census_log_init_reader(); - size_t bytes_available; - const void* record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(complete_record == record_read); - GPR_ASSERT(complete_record_size == bytes_available); - // Complete first record. - census_log_end_write(incomplete_record, incomplete_record_size); - // Have read past the incomplete record, so read_next() should return NULL. - // NB: this test also assumes our thread did not get switched to a different - // CPU between the two start_write calls - record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_read == NULL); - // Reset reader to get the newly completed record. - census_log_init_reader(); - record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(incomplete_record == record_read); - GPR_ASSERT(incomplete_record_size == bytes_available); - assert_log_empty(); - census_log_shutdown(); -} - -// Tests scenario where block being read is detached from a core and put on the -// dirty list. -void test_detached_while_reading(void) { - printf("Starting test: detached while reading\n"); - setup_test(0); - // Start a write. - static const size_t DWR_RECORD_SIZE = 10; - void* record_written = census_log_start_write(DWR_RECORD_SIZE); - GPR_ASSERT(record_written != NULL); - census_log_end_write(record_written, DWR_RECORD_SIZE); - // Read this record. - census_log_init_reader(); - size_t bytes_available; - const void* record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_read != NULL); - GPR_ASSERT(DWR_RECORD_SIZE == bytes_available); - // Now fill the log. This will move the block being read from core-local - // array to the dirty list. - while ((record_written = census_log_start_write(DWR_RECORD_SIZE))) { - census_log_end_write(record_written, DWR_RECORD_SIZE); - } - - // In this iteration, read_next() should only traverse blocks in the - // core-local array. Therefore, we expect at most gpr_cpu_num_cores() more - // blocks. As log is full, if read_next() is traversing the dirty list, we - // will get more than gpr_cpu_num_cores() blocks. - int block_read = 0; - while ((record_read = census_log_read_next(&bytes_available))) { - ++block_read; - GPR_ASSERT(block_read <= (int)gpr_cpu_num_cores()); - } - census_log_shutdown(); -} - -// Fills non-circular log with records sized such that size is a multiple of -// CENSUS_LOG_MAX_RECORD_SIZE (no per-block fragmentation). -void test_fill_log_no_fragmentation(void) { - printf("Starting test: fill log no fragmentation\n"); - const int circular = 0; - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 1 /* no fragmentation */, circular); - census_log_shutdown(); -} - -// Fills circular log with records sized such that size is a multiple of -// CENSUS_LOG_MAX_RECORD_SIZE (no per-block fragmentation). -void test_fill_circular_log_no_fragmentation(void) { - printf("Starting test: fill circular log no fragmentation\n"); - const int circular = 1; - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 1 /* no fragmentation */, circular); - census_log_shutdown(); -} - -// Fills non-circular log with records that may straddle end of a block. -void test_fill_log_with_straddling_records(void) { - printf("Starting test: fill log with straddling records\n"); - const int circular = 0; - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 0 /* block straddling records */, circular); - census_log_shutdown(); -} - -// Fills circular log with records that may straddle end of a block. -void test_fill_circular_log_with_straddling_records(void) { - printf("Starting test: fill circular log with straddling records\n"); - const int circular = 1; - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 0 /* block straddling records */, circular); - census_log_shutdown(); -} - -// Tests scenario where multiple writers and a single reader are using a log -// that is configured to discard old records. -void test_multiple_writers_circular_log(void) { - printf("Starting test: multiple writers circular log\n"); - const int circular = 1; - setup_test(circular); - multiple_writers_single_reader(circular); - census_log_shutdown(); -} - -// Tests scenario where multiple writers and a single reader are using a log -// that is configured to discard old records. -void test_multiple_writers(void) { - printf("Starting test: multiple writers\n"); - const int circular = 0; - setup_test(circular); - multiple_writers_single_reader(circular); - census_log_shutdown(); -} - -// Repeat the straddling records and multiple writers tests with a small log. -void test_small_log(void) { - printf("Starting test: small log\n"); - const int circular = 0; - census_log_initialize(0, circular); - size_t log_size = census_log_remaining_space(); - GPR_ASSERT(log_size > 0); - fill_log(log_size, 0, circular); - census_log_shutdown(); - census_log_initialize(0, circular); - multiple_writers_single_reader(circular); - census_log_shutdown(); -} - -void test_performance(void) { - for (size_t write_size = 1; write_size < CENSUS_LOG_MAX_RECORD_SIZE; - write_size *= 2) { - setup_test(0); - gpr_timespec start_time = gpr_now(GPR_CLOCK_REALTIME); - int nrecords = 0; - while (1) { - void* record = census_log_start_write(write_size); - if (record == NULL) { - break; - } - census_log_end_write(record, write_size); - nrecords++; - } - gpr_timespec write_time = - gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start_time); - double write_time_micro = - (double)write_time.tv_sec * 1000000 + (double)write_time.tv_nsec / 1000; - census_log_shutdown(); - printf( - "Wrote %d %d byte records in %.3g microseconds: %g records/us " - "(%g ns/record), %g gigabytes/s\n", - nrecords, (int)write_size, write_time_micro, - nrecords / write_time_micro, 1000 * write_time_micro / nrecords, - (double)((int)write_size * nrecords) / write_time_micro / 1000); - } -} - -int main(int argc, char** argv) { - grpc_test_init(argc, argv); - gpr_time_init(); - srand((unsigned)gpr_now(GPR_CLOCK_REALTIME).tv_nsec); - test_invalid_record_size(); - test_end_write_with_different_size(); - test_read_pending_record(); - test_read_beyond_pending_record(); - test_detached_while_reading(); - test_fill_log_no_fragmentation(); - test_fill_circular_log_no_fragmentation(); - test_fill_log_with_straddling_records(); - test_fill_circular_log_with_straddling_records(); - test_small_log(); - test_multiple_writers(); - test_multiple_writers_circular_log(); - test_performance(); - return 0; -} diff --git a/test/core/census/resource_test.c b/test/core/census/resource_test.c deleted file mode 100644 index 48fc43e45b..0000000000 --- a/test/core/census/resource_test.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * - * Copyright 2016 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/ext/census/resource.h" -#include <grpc/census.h> -#include <grpc/support/log.h> -#include <grpc/support/port_platform.h> -#include <grpc/support/useful.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include "src/core/ext/census/base_resources.h" -#include "test/core/util/test_config.h" - -// Test all the functionality for dealing with Resources. - -// Just startup and shutdown resources subsystem. -static void test_enable_disable() { - initialize_resources(); - shutdown_resources(); -} - -// A blank/empty initialization should not work. -static void test_empty_definition() { - initialize_resources(); - int32_t rid = census_define_resource(NULL, 0); - GPR_ASSERT(rid == -1); - uint8_t buffer[50] = {0}; - rid = census_define_resource(buffer, 50); - GPR_ASSERT(rid == -1); - shutdown_resources(); -} - -// Given a file name, read raw proto and define the resource included within. -// Returns resource id from census_define_resource(). -static int32_t define_resource_from_file(const char *file) { -#define BUF_SIZE 512 - uint8_t buffer[BUF_SIZE]; - FILE *input = fopen(file, "rb"); - GPR_ASSERT(input != NULL); - size_t nbytes = fread(buffer, 1, BUF_SIZE, input); - GPR_ASSERT(nbytes != 0 && nbytes < BUF_SIZE && feof(input) && !ferror(input)); - int32_t rid = census_define_resource(buffer, nbytes); - GPR_ASSERT(fclose(input) == 0); - return rid; -} - -// Test definition of a single resource, using a proto read from a file. The -// `succeed` parameter indicates whether we expect the definition to succeed or -// fail. `name` is used to check that the returned resource can be looked up by -// name. -static void test_define_single_resource(const char *file, const char *name, - bool succeed) { - gpr_log(GPR_INFO, "Test defining resource \"%s\"\n", name); - initialize_resources(); - int32_t rid = define_resource_from_file(file); - if (succeed) { - GPR_ASSERT(rid >= 0); - int32_t rid2 = census_resource_id(name); - GPR_ASSERT(rid == rid2); - } else { - GPR_ASSERT(rid < 0); - } - shutdown_resources(); -} - -// Try deleting various resources (both those that exist and those that don't). -static void test_delete_resource(const char *minimal_good, const char *full) { - initialize_resources(); - // Try deleting resource before any are defined. - census_delete_resource(0); - // Create and check a couple of resources. - int32_t rid1 = define_resource_from_file(minimal_good); - int32_t rid2 = define_resource_from_file(full); - GPR_ASSERT(rid1 >= 0 && rid2 >= 0 && rid1 != rid2); - int32_t rid3 = census_resource_id("minimal_good"); - int32_t rid4 = census_resource_id("full_resource"); - GPR_ASSERT(rid1 == rid3 && rid2 == rid4); - // Try deleting non-existant resources. - census_delete_resource(-1); - census_delete_resource(rid1 + rid2 + 1); - census_delete_resource(10000000); - // Delete one of the previously defined resources and check for deletion. - census_delete_resource(rid1); - rid3 = census_resource_id("minimal_good"); - GPR_ASSERT(rid3 < 0); - // Check that re-adding works. - rid1 = define_resource_from_file(minimal_good); - GPR_ASSERT(rid1 >= 0); - rid3 = census_resource_id("minimal_good"); - GPR_ASSERT(rid1 == rid3); - shutdown_resources(); -} - -// Test define base resources. -static void test_base_resources() { - initialize_resources(); - define_base_resources(); - int32_t rid1 = census_resource_id("client_rpc_latency"); - int32_t rid2 = census_resource_id("server_rpc_latency"); - GPR_ASSERT(rid1 >= 0 && rid2 >= 0 && rid1 != rid2); - shutdown_resources(); -} - -int main(int argc, char **argv) { - const char *resource_empty_name_pb, *resource_full_pb, - *resource_minimal_good_pb, *resource_no_name_pb, - *resource_no_numerator_pb, *resource_no_unit_pb; - if (argc == 7) { - resource_empty_name_pb = argv[1]; - resource_full_pb = argv[2]; - resource_minimal_good_pb = argv[3]; - resource_no_name_pb = argv[4]; - resource_no_numerator_pb = argv[5]; - resource_no_unit_pb = argv[6]; - } else { - GPR_ASSERT(argc == 1); - resource_empty_name_pb = "test/core/census/data/resource_empty_name.pb"; - resource_full_pb = "test/core/census/data/resource_full.pb"; - resource_minimal_good_pb = "test/core/census/data/resource_minimal_good.pb"; - resource_no_name_pb = "test/core/census/data/resource_no_name.pb"; - resource_no_numerator_pb = "test/core/census/data/resource_no_numerator.pb"; - resource_no_unit_pb = "test/core/census/data/resource_no_unit.pb"; - } - grpc_test_init(argc, argv); - test_enable_disable(); - test_empty_definition(); - test_define_single_resource(resource_minimal_good_pb, "minimal_good", true); - test_define_single_resource(resource_full_pb, "full_resource", true); - test_define_single_resource(resource_no_name_pb, "resource_no_name", false); - test_define_single_resource(resource_no_numerator_pb, "resource_no_numerator", - false); - test_define_single_resource(resource_no_unit_pb, "resource_no_unit", false); - test_define_single_resource(resource_empty_name_pb, "resource_empty_name", - false); - test_delete_resource(resource_minimal_good_pb, resource_full_pb); - test_base_resources(); - return 0; -} diff --git a/test/core/census/trace_context_test.c b/test/core/census/trace_context_test.c deleted file mode 100644 index 6eb831a85e..0000000000 --- a/test/core/census/trace_context_test.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * - * Copyright 2016 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 <grpc/census.h> -#include <grpc/support/log.h> -#include <grpc/support/port_platform.h> -#include <grpc/support/useful.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include "src/core/ext/census/base_resources.h" -#include "src/core/ext/census/resource.h" -#include "test/core/util/test_config.h" - -#include "src/core/ext/census/gen/trace_context.pb.h" -#include "src/core/ext/census/trace_context.h" -#include "third_party/nanopb/pb_decode.h" -#include "third_party/nanopb/pb_encode.h" - -#define BUF_SIZE 256 - -/* Encodes a TraceContext structure (ctxt1) to a buffer, and then decodes it -to a second TraceContext (ctxt2). Validates that the resulting TraceContext -has a span_id, trace_id, and that the values are equal to those in initial -TraceContext. On success, returns true. If encode_trace_context returns 0, -decode_trace_context fails, or the resulting TraceContext is missing a trace_id -or span_id, it will return false. */ -bool validate_encode_decode_context(google_trace_TraceContext *ctxt1, - uint8_t *buffer, size_t buf_size) { - google_trace_TraceContext ctxt2 = google_trace_TraceContext_init_zero; - size_t msg_length; - - msg_length = encode_trace_context(ctxt1, buffer, buf_size); - if (msg_length == 0) { - return false; - } - - if (!decode_trace_context(&ctxt2, buffer, msg_length)) { - return false; - } - - if (!ctxt2.has_trace_id_hi || !ctxt2.has_trace_id_lo || !ctxt2.has_span_id) { - return false; - } - - GPR_ASSERT(ctxt1->trace_id_hi == ctxt2.trace_id_hi && - ctxt1->trace_id_lo == ctxt2.trace_id_lo && - ctxt1->span_id == ctxt2.span_id && - ctxt1->has_span_options == ctxt2.has_span_options && - (ctxt1->has_span_options - ? ctxt1->span_options == ctxt2.span_options - : true)); - - return true; -} - -/* Decodes a proto-encoded TraceContext from a buffer. If decode_trace_context -fails or the resulting TraceContext is missing a trace_id or span_id it will -return false, otherwise returns true. */ -bool validate_decode_context(google_trace_TraceContext *ctxt, uint8_t *buffer, - size_t msg_length) { - // Validate the decoding of a context written to buffer. - if (!decode_trace_context(ctxt, buffer, msg_length)) { - return false; - } - - if (!ctxt->has_trace_id_hi || !ctxt->has_trace_id_lo || !ctxt->has_span_id) { - return false; - } - - return true; -} - -/* Read an encoded trace context from a file. Validates that the decoding -gives the expected result (succeed). */ -static void read_and_validate_context_from_file(google_trace_TraceContext *ctxt, - const char *file, - const bool succeed) { - uint8_t buffer[BUF_SIZE]; - FILE *input = fopen(file, "rb"); - GPR_ASSERT(input != NULL); - size_t nbytes = fread(buffer, 1, BUF_SIZE, input); - GPR_ASSERT(nbytes <= BUF_SIZE && feof(input) && !ferror(input)); - bool res = validate_decode_context(ctxt, buffer, nbytes); - GPR_ASSERT(res == succeed); - GPR_ASSERT(fclose(input) == 0); -} - -// Test full proto-buffer. -static void test_full() { - google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; - read_and_validate_context_from_file( - &ctxt, "test/core/census/data/context_full.pb", true); -} - -// Test empty proto-buffer. -static void test_empty() { - google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; - read_and_validate_context_from_file( - &ctxt, "test/core/census/data/context_empty.pb", false); -} - -// Test proto-buffer with only trace_id. -static void test_trace_only() { - google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; - read_and_validate_context_from_file( - &ctxt, "test/core/census/data/context_trace_only.pb", false); -} - -// Test proto-buffer with only span_id. -static void test_span_only() { - google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; - read_and_validate_context_from_file( - &ctxt, "test/core/census/data/context_span_only.pb", false); -} - -// Test proto-buffer without span_options value. -static void test_no_span_options() { - google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; - read_and_validate_context_from_file( - &ctxt, "test/core/census/data/context_no_span_options.pb", true); - GPR_ASSERT(ctxt.has_span_options == false && ctxt.span_options == 0); -} - -static void test_encode_decode() { - uint8_t buffer[BUF_SIZE] = {0}; - - google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero; - ctxt1.has_trace_id_hi = true; - ctxt1.has_trace_id_lo = true; - ctxt1.trace_id_lo = 1; - ctxt1.trace_id_hi = 2; - ctxt1.has_span_id = true; - ctxt1.span_id = 3; - validate_encode_decode_context(&ctxt1, buffer, sizeof(buffer)); - - // Missing trace_id. This should fail. - google_trace_TraceContext ctxt2 = google_trace_TraceContext_init_zero; - ctxt2.has_trace_id_hi = false; - ctxt2.has_trace_id_lo = false; - ctxt2.has_span_id = true; - validate_encode_decode_context(&ctxt2, buffer, sizeof(buffer)); -} - -// Test a corrupted proto-buffer. This should fail. -static void test_corrupt() { - uint8_t buffer[BUF_SIZE] = {0}; - google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero; - size_t msg_length; - - ctxt1.has_trace_id_hi = true; - ctxt1.has_trace_id_lo = true; - ctxt1.trace_id_lo = 1; - ctxt1.trace_id_hi = 2; - ctxt1.has_span_id = true; - ctxt1.span_id = 3; - ctxt1.has_span_options = true; - ctxt1.span_options = SPAN_OPTIONS_IS_SAMPLED; - msg_length = encode_trace_context(&ctxt1, buffer, sizeof(buffer)); - - /* Corrupt some bytes. 255 (0xFF) should be illegal for the first byte of the - proto encoded object. */ - buffer[0] = 255; - - bool res = validate_decode_context(&ctxt1, buffer, msg_length); - GPR_ASSERT(res == false); -} - -static void test_buffer_size() { - // This buffer is too small. This should fail. - uint8_t buffer[16] = {0}; - google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero; - size_t msg_length; - - ctxt1.has_trace_id_hi = true; - ctxt1.has_trace_id_lo = true; - ctxt1.trace_id_lo = 1; - ctxt1.trace_id_hi = 2; - ctxt1.has_span_id = true; - ctxt1.span_id = 3; - ctxt1.has_span_options = true; - ctxt1.span_options = SPAN_OPTIONS_IS_SAMPLED; - msg_length = encode_trace_context(&ctxt1, buffer, sizeof(buffer)); - - GPR_ASSERT(msg_length == 0); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_full(); - test_empty(); - test_trace_only(); - test_span_only(); - test_encode_decode(); - test_corrupt(); - test_no_span_options(); - test_buffer_size(); - - return 0; -} diff --git a/test/core/client_channel/lb_policies_test.c b/test/core/client_channel/lb_policies_test.c index ba37cd673f..0e47d8f324 100644 --- a/test/core/client_channel/lb_policies_test.c +++ b/test/core/client_channel/lb_policies_test.c @@ -53,8 +53,8 @@ typedef struct request_sequences { size_t n; /* number of iterations */ int *connections; /* indexed by the interation number, value is the index of the server it connected to or -1 if none */ - int *connectivity_states; /* indexed by the interation number, value is the - client connectivity state */ + /* indexed by the interation number, value is the client connectivity state */ + grpc_connectivity_state *connectivity_states; } request_sequences; typedef void (*verifier_fn)(const servers_fixture *, grpc_channel *, diff --git a/test/core/debug/stats_test.cc b/test/core/debug/stats_test.cc index c85ab3598a..501581952d 100644 --- a/test/core/debug/stats_test.cc +++ b/test/core/debug/stats_test.cc @@ -20,7 +20,11 @@ extern "C" { #include "src/core/lib/debug/stats.h" } +#include <mutex> +#include <thread> + #include <grpc/grpc.h> +#include <grpc/support/cpu.h> #include <grpc/support/log.h> #include <gtest/gtest.h> @@ -79,38 +83,59 @@ static int FindExpectedBucket(int i, int j) { grpc_stats_histo_bucket_boundaries[i] - 1; } -TEST(StatsTest, IncHistogram) { - for (int i = 0; i < GRPC_STATS_HISTOGRAM_COUNT; i++) { - std::vector<int> test_values; - for (int j = -1000; - j < - grpc_stats_histo_bucket_boundaries[i] - [grpc_stats_histo_buckets[i] - 1] + - 1000; - j++) { - test_values.push_back(j); - } - std::random_shuffle(test_values.begin(), test_values.end()); - if (test_values.size() > 10000) { - test_values.resize(10000); - } +class HistogramTest : public ::testing::TestWithParam<int> {}; + +TEST_P(HistogramTest, IncHistogram) { + const int kHistogram = GetParam(); + std::vector<std::thread> threads; + int cur_bucket = 0; + auto run = [kHistogram](const std::vector<int>& test_values, + int expected_bucket) { + gpr_log(GPR_DEBUG, "expected_bucket:%d nvalues=%" PRIdPTR, expected_bucket, + test_values.size()); for (auto j : test_values) { Snapshot snapshot; - int expected_bucket = FindExpectedBucket(i, j); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_stats_inc_histogram[i](&exec_ctx, j); + grpc_stats_inc_histogram[kHistogram](&exec_ctx, j); grpc_exec_ctx_finish(&exec_ctx); auto delta = snapshot.delta(); - EXPECT_EQ(delta.histograms[grpc_stats_histo_start[i] + expected_bucket], - 1); + EXPECT_EQ( + delta + .histograms[grpc_stats_histo_start[kHistogram] + expected_bucket], + 1) + << "\nhistogram:" << kHistogram + << "\nexpected_bucket:" << expected_bucket << "\nj:" << j; + } + }; + std::vector<int> test_values; + for (int j = -1000; + j < + grpc_stats_histo_bucket_boundaries[kHistogram] + [grpc_stats_histo_buckets[kHistogram] - + 1] + + 1000; + j++) { + int expected_bucket = FindExpectedBucket(kHistogram, j); + if (cur_bucket != expected_bucket) { + threads.emplace_back( + [test_values, run, cur_bucket]() { run(test_values, cur_bucket); }); + cur_bucket = expected_bucket; + test_values.clear(); } + test_values.push_back(j); + } + run(test_values, cur_bucket); + for (auto& t : threads) { + t.join(); } } +INSTANTIATE_TEST_CASE_P(HistogramTestCases, HistogramTest, + ::testing::Range<int>(0, GRPC_STATS_HISTOGRAM_COUNT)); + } // namespace testing } // namespace grpc diff --git a/test/core/end2end/bad_server_response_test.c b/test/core/end2end/bad_server_response_test.c index eeabc769d3..2070fa5b02 100644 --- a/test/core/end2end/bad_server_response_test.c +++ b/test/core/end2end/bad_server_response_test.c @@ -62,8 +62,6 @@ #define HTTP2_DETAIL_MSG(STATUS_CODE) \ "Received http2 header with status: " #STATUS_CODE -#define UNPARSEABLE_DETAIL_MSG "Failed parsing HTTP/2" - #define HTTP1_DETAIL_MSG "Trying to connect an http1.x server" /* TODO(zyc) Check the content of incomming data instead of using this length */ @@ -208,8 +206,10 @@ static void start_rpc(int target_port, grpc_status_code expected_status, cq_verify(cqv); GPR_ASSERT(status == expected_status); - GPR_ASSERT(-1 != grpc_slice_slice(details, grpc_slice_from_static_string( - expected_detail))); + if (expected_detail != NULL) { + GPR_ASSERT(-1 != grpc_slice_slice(details, grpc_slice_from_static_string( + expected_detail))); + } grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); @@ -330,8 +330,8 @@ int main(int argc, char **argv) { HTTP2_DETAIL_MSG(502)); /* unparseable response */ - run_test(UNPARSEABLE_RESP, sizeof(UNPARSEABLE_RESP) - 1, - GRPC_STATUS_UNAVAILABLE, UNPARSEABLE_DETAIL_MSG); + run_test(UNPARSEABLE_RESP, sizeof(UNPARSEABLE_RESP) - 1, GRPC_STATUS_UNKNOWN, + NULL); /* http1 response */ run_test(HTTP1_RESP, sizeof(HTTP1_RESP) - 1, GRPC_STATUS_UNAVAILABLE, diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index 33fd97f3bd..f7f996d5c1 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -24,15 +24,15 @@ import hashlib FixtureOptions = collections.namedtuple( 'FixtureOptions', - 'fullstack includes_proxy dns_resolver name_resolution secure platforms ci_mac tracing exclude_configs exclude_iomgrs large_writes enables_compression supports_compression is_inproc is_http2 supports_proxy_auth') + 'fullstack includes_proxy dns_resolver name_resolution secure platforms ci_mac tracing exclude_configs exclude_iomgrs large_writes enables_compression supports_compression is_inproc is_http2 supports_proxy_auth supports_write_buffering') default_unsecure_fixture_options = FixtureOptions( - True, False, True, True, False, ['windows', 'linux', 'mac', 'posix'], True, False, [], [], True, False, True, False, True, False) + True, False, True, True, False, ['windows', 'linux', 'mac', 'posix'], True, False, [], [], True, False, True, False, True, False, True) socketpair_unsecure_fixture_options = default_unsecure_fixture_options._replace(fullstack=False, dns_resolver=False) default_secure_fixture_options = default_unsecure_fixture_options._replace(secure=True) uds_fixture_options = default_unsecure_fixture_options._replace(dns_resolver=False, platforms=['linux', 'mac', 'posix'], exclude_iomgrs=['uv']) fd_unsecure_fixture_options = default_unsecure_fixture_options._replace( dns_resolver=False, fullstack=False, platforms=['linux', 'mac', 'posix'], exclude_iomgrs=['uv']) -inproc_fixture_options = default_unsecure_fixture_options._replace(dns_resolver=False, fullstack=False, name_resolution=False, supports_compression=False, is_inproc=True, is_http2=False) +inproc_fixture_options = default_unsecure_fixture_options._replace(dns_resolver=False, fullstack=False, name_resolution=False, supports_compression=False, is_inproc=True, is_http2=False, supports_write_buffering=False) # maps fixture name to whether it requires the security library END2END_FIXTURES = { @@ -60,7 +60,6 @@ END2END_FIXTURES = { 'h2_sockpair+trace': socketpair_unsecure_fixture_options._replace( ci_mac=False, tracing=True, large_writes=False, exclude_iomgrs=['uv']), 'h2_ssl': default_secure_fixture_options, - 'h2_ssl_cert': default_secure_fixture_options, 'h2_ssl_proxy': default_secure_fixture_options._replace( includes_proxy=True, ci_mac=False, exclude_iomgrs=['uv']), 'h2_uds': uds_fixture_options, @@ -69,8 +68,8 @@ END2END_FIXTURES = { TestOptions = collections.namedtuple( 'TestOptions', - 'needs_fullstack needs_dns needs_names proxyable secure traceable cpu_cost exclude_iomgrs large_writes flaky allows_compression needs_compression exclude_inproc needs_http2 needs_proxy_auth') -default_test_options = TestOptions(False, False, False, True, False, True, 1.0, [], False, False, True, False, False, False, False) + 'needs_fullstack needs_dns needs_names proxyable secure traceable cpu_cost exclude_iomgrs large_writes flaky allows_compression needs_compression exclude_inproc needs_http2 needs_proxy_auth needs_write_buffering') +default_test_options = TestOptions(False, False, False, True, False, True, 1.0, [], False, False, True, False, False, False, False, False) connectivity_test_options = default_test_options._replace(needs_fullstack=True) LOWCPU = 0.1 @@ -147,8 +146,10 @@ END2END_TESTS = { 'streaming_error_response': default_test_options._replace(cpu_cost=LOWCPU), 'trailing_metadata': default_test_options, 'workaround_cronet_compression': default_test_options, - 'write_buffering': default_test_options._replace(cpu_cost=LOWCPU), - 'write_buffering_at_end': default_test_options._replace(cpu_cost=LOWCPU), + 'write_buffering': default_test_options._replace(cpu_cost=LOWCPU, + needs_write_buffering=True), + 'write_buffering_at_end': default_test_options._replace(cpu_cost=LOWCPU, + needs_write_buffering=True), } @@ -186,6 +187,9 @@ def compatible(f, t): if END2END_TESTS[t].needs_proxy_auth: if not END2END_FIXTURES[f].supports_proxy_auth: return False + if END2END_TESTS[t].needs_write_buffering: + if not END2END_FIXTURES[f].supports_write_buffering: + return False return True diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index 9bbba26108..89a95edfd7 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -21,7 +21,8 @@ load("//bazel:grpc_build_system.bzl", "grpc_sh_test", "grpc_cc_binary", "grpc_cc def fixture_options(fullstack=True, includes_proxy=False, dns_resolver=True, name_resolution=True, secure=True, tracing=False, platforms=['windows', 'linux', 'mac', 'posix'], - is_inproc=False, is_http2=True, supports_proxy_auth=False): + is_inproc=False, is_http2=True, supports_proxy_auth=False, + supports_write_buffering=True): return struct( fullstack=fullstack, includes_proxy=includes_proxy, @@ -31,7 +32,8 @@ def fixture_options(fullstack=True, includes_proxy=False, dns_resolver=True, tracing=tracing, is_inproc=is_inproc, is_http2=is_http2, - supports_proxy_auth=supports_proxy_auth + supports_proxy_auth=supports_proxy_auth, + supports_write_buffering=supports_write_buffering #platforms=platforms ) @@ -56,20 +58,19 @@ END2END_FIXTURES = { 'h2_sockpair+trace': fixture_options(fullstack=False, dns_resolver=False, tracing=True), 'h2_ssl': fixture_options(secure=True), - 'h2_ssl_cert': fixture_options(secure=True), 'h2_ssl_proxy': fixture_options(includes_proxy=True, secure=True), 'h2_uds': fixture_options(dns_resolver=False, platforms=['linux', 'mac', 'posix']), 'inproc': fixture_options(fullstack=False, dns_resolver=False, name_resolution=False, is_inproc=True, - is_http2=False), + is_http2=False, supports_write_buffering=False), } def test_options(needs_fullstack=False, needs_dns=False, needs_names=False, proxyable=True, secure=False, traceable=False, exclude_inproc=False, needs_http2=False, - needs_proxy_auth=False): + needs_proxy_auth=False, needs_write_buffering=False): return struct( needs_fullstack=needs_fullstack, needs_dns=needs_dns, @@ -79,7 +80,8 @@ def test_options(needs_fullstack=False, needs_dns=False, needs_names=False, traceable=traceable, exclude_inproc=exclude_inproc, needs_http2=needs_http2, - needs_proxy_auth=needs_proxy_auth + needs_proxy_auth=needs_proxy_auth, + needs_write_buffering=needs_write_buffering ) @@ -145,8 +147,8 @@ END2END_TESTS = { 'authority_not_supported': test_options(), 'filter_latency': test_options(), 'workaround_cronet_compression': test_options(), - 'write_buffering': test_options(), - 'write_buffering_at_end': test_options(), + 'write_buffering': test_options(needs_write_buffering=True), + 'write_buffering_at_end': test_options(needs_write_buffering=True), } @@ -175,6 +177,9 @@ def compatible(fopt, topt): if topt.needs_proxy_auth: if not fopt.supports_proxy_auth: return False + if topt.needs_write_buffering: + if not fopt.supports_write_buffering: + return False return True diff --git a/test/core/end2end/fixtures/h2_ssl_cert.c b/test/core/end2end/h2_ssl_cert_test.cc index f0a2ee5430..6da5e8396e 100644 --- a/test/core/end2end/fixtures/h2_ssl_cert.c +++ b/test/core/end2end/h2_ssl_cert_test.cc @@ -16,7 +16,9 @@ * */ +extern "C" { #include "test/core/end2end/end2end_tests.h" +} #include <stdio.h> #include <string.h> @@ -25,6 +27,7 @@ #include <grpc/support/host_port.h> #include <grpc/support/log.h> +extern "C" { #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/support/env.h" @@ -34,8 +37,12 @@ #include "test/core/end2end/data/ssl_test_data.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" +} -extern void simple_request(grpc_end2end_test_config config); +#include <gtest/gtest.h> + +namespace grpc { +namespace testing { typedef struct fullstack_secure_fixture_data { char *localaddr; @@ -46,7 +53,8 @@ static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack( grpc_end2end_test_fixture f; int port = grpc_pick_unused_port_or_die(); fullstack_secure_fixture_data *ffd = - gpr_malloc(sizeof(fullstack_secure_fixture_data)); + static_cast<fullstack_secure_fixture_data *>( + gpr_malloc(sizeof(fullstack_secure_fixture_data))); memset(&f, 0, sizeof(f)); gpr_join_host_port(&ffd->localaddr, "localhost", port); @@ -69,7 +77,8 @@ static void process_auth_failure(void *state, grpc_auth_context *ctx, static void chttp2_init_client_secure_fullstack( grpc_end2end_test_fixture *f, grpc_channel_args *client_args, grpc_channel_credentials *creds) { - fullstack_secure_fixture_data *ffd = f->fixture_data; + fullstack_secure_fixture_data *ffd = + static_cast<fullstack_secure_fixture_data *>(f->fixture_data); f->client = grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL); GPR_ASSERT(f->client != NULL); @@ -79,7 +88,8 @@ static void chttp2_init_client_secure_fullstack( static void chttp2_init_server_secure_fullstack( grpc_end2end_test_fixture *f, grpc_channel_args *server_args, grpc_server_credentials *server_creds) { - fullstack_secure_fixture_data *ffd = f->fixture_data; + fullstack_secure_fixture_data *ffd = + static_cast<fullstack_secure_fixture_data *>(f->fixture_data); if (f->server) { grpc_server_destroy(f->server); } @@ -92,7 +102,8 @@ static void chttp2_init_server_secure_fullstack( } void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { - fullstack_secure_fixture_data *ffd = f->fixture_data; + fullstack_secure_fixture_data *ffd = + static_cast<fullstack_secure_fixture_data *>(f->fixture_data); gpr_free(ffd->localaddr); gpr_free(ffd); } @@ -166,9 +177,10 @@ typedef enum { NONE, SELF_SIGNED, SIGNED, BAD_CERT_PAIR } certtype; } \ ssl_creds = \ grpc_ssl_credentials_create(test_root_cert, key_cert_pair, NULL); \ - grpc_arg ssl_name_override = {GRPC_ARG_STRING, \ - GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, \ - {"foo.test.google.fr"}}; \ + grpc_arg ssl_name_override = { \ + GRPC_ARG_STRING, \ + const_cast<char *>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), \ + {const_cast<char *>("foo.test.google.fr")}}; \ grpc_channel_args *new_client_args = \ grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1); \ chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds); \ @@ -248,18 +260,6 @@ static grpc_end2end_test_config_wrapper configs[] = { static void *tag(intptr_t t) { return (void *)t; } -static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, - const char *test_name, - grpc_channel_args *client_args, - grpc_channel_args *server_args) { - grpc_end2end_test_fixture f; - gpr_log(GPR_INFO, "%s/%s", test_name, config.name); - f = config.create_fixture(client_args, server_args); - config.init_server(&f, server_args); - config.init_client(&f, client_args); - return f; -} - static gpr_timespec n_seconds_time(int n) { return grpc_timeout_seconds_to_deadline(n); } @@ -332,15 +332,40 @@ static void simple_request_body(grpc_end2end_test_fixture f, cq_verifier_destroy(cqv); } +class H2SslCertTest + : public ::testing::TestWithParam<grpc_end2end_test_config_wrapper> { + protected: + H2SslCertTest() { + gpr_log(GPR_INFO, "SSL_CERT_tests/%s", GetParam().config.name); + } + void SetUp() override { + fixture_ = GetParam().config.create_fixture(nullptr, nullptr); + GetParam().config.init_server(&fixture_, nullptr); + GetParam().config.init_client(&fixture_, nullptr); + } + void TearDown() override { + end_test(&fixture_); + GetParam().config.tear_down_data(&fixture_); + } + + grpc_end2end_test_fixture fixture_; +}; + +TEST_P(H2SslCertTest, SimpleRequestBody) { + simple_request_body(fixture_, GetParam().result); +} + +INSTANTIATE_TEST_CASE_P(H2SslCert, H2SslCertTest, ::testing::ValuesIn(configs)); + +} // namespace testing +} // namespace grpc + int main(int argc, char **argv) { - size_t i; FILE *roots_file; size_t roots_size = strlen(test_root_cert); char *roots_filename; grpc_test_init(argc, argv); - grpc_end2end_tests_pre_init(); - /* Set the SSL roots env var. */ roots_file = gpr_tmpfile("chttp2_simple_ssl_cert_fullstack_test", &roots_filename); @@ -351,21 +376,13 @@ int main(int argc, char **argv) { gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_filename); grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_test_fixture f = - begin_test(configs[i].config, "SSL_CERT_tests", NULL, NULL); - - simple_request_body(f, configs[i].result); - end_test(&f); - configs[i].config.tear_down_data(&f); - } - + ::testing::InitGoogleTest(&argc, argv); + int ret = RUN_ALL_TESTS(); grpc_shutdown(); /* Cleanup. */ remove(roots_filename); gpr_free(roots_filename); - return 0; + return ret; } diff --git a/test/core/end2end/tests/bad_ping.c b/test/core/end2end/tests/bad_ping.c index d442f12480..34cc8e78cd 100644 --- a/test/core/end2end/tests/bad_ping.c +++ b/test/core/end2end/tests/bad_ping.c @@ -203,7 +203,6 @@ static void test_bad_ping(grpc_end2end_test_config config) { // The connection should be closed immediately after the misbehaved pings, // the in-progress RPC should fail. GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "Endpoint read failed")); GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); validate_host_override_string("foo.test.google.fr:1234", call_details.host, config); diff --git a/test/core/end2end/tests/cancel_after_accept.c b/test/core/end2end/tests/cancel_after_accept.c index c3ac0c3201..96262b1156 100644 --- a/test/core/end2end/tests/cancel_after_accept.c +++ b/test/core/end2end/tests/cancel_after_accept.c @@ -130,7 +130,8 @@ static void test_cancel_after_accept(grpc_end2end_test_config config, "{\n" " \"methodConfig\": [ {\n" " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" + " { \"service\": \"service\", \"method\": \"method\" },\n" + " { \"service\": \"unused\" }\n" " ],\n" " \"timeout\": \"5s\"\n" " } ]\n" diff --git a/test/core/end2end/tests/keepalive_timeout.c b/test/core/end2end/tests/keepalive_timeout.c index c4280149c7..0053368ecc 100644 --- a/test/core/end2end/tests/keepalive_timeout.c +++ b/test/core/end2end/tests/keepalive_timeout.c @@ -193,7 +193,7 @@ static void test_keepalive_timeout(grpc_end2end_test_config config) { char *details_str = grpc_slice_to_c_string(details); char *method_str = grpc_slice_to_c_string(call_details.method); - GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); + GPR_ASSERT(status == GRPC_STATUS_INTERNAL); GPR_ASSERT(0 == grpc_slice_str_cmp(details, "keepalive watchdog timeout")); GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); validate_host_override_string("foo.test.google.fr:1234", call_details.host, diff --git a/test/core/end2end/tests/max_connection_age.c b/test/core/end2end/tests/max_connection_age.c index 4119087619..b6daa59d7b 100644 --- a/test/core/end2end/tests/max_connection_age.c +++ b/test/core/end2end/tests/max_connection_age.c @@ -203,8 +203,7 @@ static void test_max_age_forcibly_close(grpc_end2end_test_config config) { /* The connection should be closed immediately after the max age grace period, the in-progress RPC should fail. */ - GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "Endpoint read failed")); + GPR_ASSERT(status == GRPC_STATUS_INTERNAL); GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); validate_host_override_string("foo.test.google.fr:1234", call_details.host, config); diff --git a/test/core/end2end/tests/max_message_length.c b/test/core/end2end/tests/max_message_length.c index 01eb8d365e..8925de9fe4 100644 --- a/test/core/end2end/tests/max_message_length.c +++ b/test/core/end2end/tests/max_message_length.c @@ -138,7 +138,8 @@ static void test_max_message_length_on_request(grpc_end2end_test_config config, ? "{\n" " \"methodConfig\": [ {\n" " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" + " { \"service\": \"service\", \"method\": \"method\" },\n" + " { \"service\": \"unused\" }\n" " ],\n" " \"maxRequestMessageBytes\": \"5\"\n" " } ]\n" diff --git a/test/core/end2end/tests/shutdown_finishes_calls.c b/test/core/end2end/tests/shutdown_finishes_calls.c index cef571b490..f90359f09a 100644 --- a/test/core/end2end/tests/shutdown_finishes_calls.c +++ b/test/core/end2end/tests/shutdown_finishes_calls.c @@ -159,7 +159,9 @@ static void test_early_server_shutdown_finishes_inflight_calls( grpc_server_destroy(f.server); - GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); + // new code should give INTERNAL, some older code will give UNAVAILABLE + GPR_ASSERT(status == GRPC_STATUS_INTERNAL || + status == GRPC_STATUS_UNAVAILABLE); GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); validate_host_override_string("foo.test.google.fr:1234", call_details.host, config); diff --git a/test/core/end2end/tests/streaming_error_response.c b/test/core/end2end/tests/streaming_error_response.c index 9d562b9090..8891b8674c 100644 --- a/test/core/end2end/tests/streaming_error_response.c +++ b/test/core/end2end/tests/streaming_error_response.c @@ -183,7 +183,6 @@ static void test(grpc_end2end_test_config config, bool request_status_early) { GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - cq_verify(cqv); if (!request_status_early) { memset(ops, 0, sizeof(ops)); diff --git a/test/core/iomgr/pollset_set_test.c b/test/core/iomgr/pollset_set_test.c index 3dd4bc887c..cddc146ce0 100644 --- a/test/core/iomgr/pollset_set_test.c +++ b/test/core/iomgr/pollset_set_test.c @@ -24,6 +24,7 @@ #include <string.h> #include <unistd.h> +#include <grpc/grpc.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/useful.h> @@ -430,14 +431,13 @@ void pollset_set_test_empty_pollset() { } int main(int argc, char **argv) { - const char *poll_strategy = grpc_get_poll_strategy_name(); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_test_init(argc, argv); - grpc_iomgr_init(&exec_ctx); - grpc_iomgr_start(&exec_ctx); + grpc_init(); + const char *poll_strategy = grpc_get_poll_strategy_name(); if (poll_strategy != NULL && - (strcmp(poll_strategy, "epoll") == 0 || + (strcmp(poll_strategy, "epollsig") == 0 || strcmp(poll_strategy, "epoll-threadpool") == 0)) { pollset_set_test_basic(); pollset_set_test_dup_fds(); @@ -449,8 +449,8 @@ int main(int argc, char **argv) { poll_strategy); } - grpc_iomgr_shutdown(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); return 0; } #else /* defined(GRPC_LINUX_EPOLL) */ diff --git a/test/core/iomgr/tcp_client_uv_test.c b/test/core/iomgr/tcp_client_uv_test.c index 0f1db4705b..edfccbe867 100644 --- a/test/core/iomgr/tcp_client_uv_test.c +++ b/test/core/iomgr/tcp_client_uv_test.c @@ -42,8 +42,8 @@ static grpc_pollset *g_pollset; static int g_connections_complete = 0; static grpc_endpoint *g_connecting = NULL; -static gpr_timespec test_deadline(void) { - return grpc_timeout_seconds_to_deadline(10); +static grpc_millis test_deadline(void) { + return grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(10)); } static void finish_connection(grpc_exec_ctx *exec_ctx) { @@ -110,7 +110,7 @@ void test_succeeds(void) { (int *)&resolved_addr.len) == 0); GRPC_CLOSURE_INIT(&done, must_succeed, NULL, grpc_schedule_on_exec_ctx); grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, NULL, NULL, - &resolved_addr, gpr_inf_future(GPR_CLOCK_REALTIME)); + &resolved_addr, GRPC_MILLIS_INF_FUTURE); gpr_mu_lock(g_mu); @@ -119,8 +119,8 @@ void test_succeeds(void) { GPR_ASSERT(GRPC_LOG_IF_ERROR( "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, - gpr_now(GPR_CLOCK_MONOTONIC), - grpc_timeout_seconds_to_deadline(5)))); + grpc_timespec_to_millis_round_up( + grpc_timeout_seconds_to_deadline(5))))); gpr_mu_unlock(g_mu); grpc_exec_ctx_flush(&exec_ctx); gpr_mu_lock(g_mu); @@ -154,7 +154,7 @@ void test_fails(void) { /* connect to a broken address */ GRPC_CLOSURE_INIT(&done, must_fail, NULL, grpc_schedule_on_exec_ctx); grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, NULL, NULL, - &resolved_addr, gpr_inf_future(GPR_CLOCK_REALTIME)); + &resolved_addr, GRPC_MILLIS_INF_FUTURE); gpr_mu_lock(g_mu); @@ -162,17 +162,17 @@ void test_fails(void) { while (g_connections_complete == connections_complete_before) { grpc_pollset_worker *worker = NULL; gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); - gpr_timespec polling_deadline = test_deadline(); - switch (grpc_timer_check(&exec_ctx, now, &polling_deadline)) { + grpc_millis polling_deadline = test_deadline(); + switch (grpc_timer_check(&exec_ctx, &polling_deadline)) { case GRPC_TIMERS_FIRED: break; case GRPC_TIMERS_NOT_CHECKED: - polling_deadline = now; + polling_deadline = grpc_timespec_to_millis_round_up(now); /* fall through */ case GRPC_TIMERS_CHECKED_AND_EMPTY: GPR_ASSERT(GRPC_LOG_IF_ERROR( "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, - now, polling_deadline))); + polling_deadline))); break; } gpr_mu_unlock(g_mu); diff --git a/test/core/iomgr/tcp_server_uv_test.c b/test/core/iomgr/tcp_server_uv_test.c index bd8ccb4f60..9fafd3177a 100644 --- a/test/core/iomgr/tcp_server_uv_test.c +++ b/test/core/iomgr/tcp_server_uv_test.c @@ -207,7 +207,7 @@ static void tcp_connect(grpc_exec_ctx *exec_ctx, const struct sockaddr *remote, GPR_ASSERT(GRPC_LOG_IF_ERROR( "pollset_work", grpc_pollset_work(exec_ctx, g_pollset, &worker, - gpr_now(GPR_CLOCK_MONOTONIC), deadline))); + grpc_timespec_to_millis_round_up(deadline)))); gpr_mu_unlock(g_mu); grpc_exec_ctx_finish(exec_ctx); gpr_mu_lock(g_mu); @@ -246,7 +246,7 @@ static void test_connect(unsigned n) { GPR_ASSERT(GRPC_ERROR_NONE == grpc_tcp_server_add_port(s, &resolved_addr, &svr_port)); GPR_ASSERT(svr_port > 0); - GPR_ASSERT(uv_ip6_addr("::", svr_port, (struct sockaddr_in6 *)addr) == 0); + GPR_ASSERT((uv_ip6_addr("::", svr_port, (struct sockaddr_in6 *)addr)) == 0); /* Cannot use wildcard (port==0), because add_port() will try to reuse the same port as a previous add_port(). */ svr1_port = grpc_pick_unused_port_or_die(); diff --git a/test/core/security/BUILD b/test/core/security/BUILD index dc41759922..83b1747648 100644 --- a/test/core/security/BUILD +++ b/test/core/security/BUILD @@ -91,6 +91,18 @@ grpc_cc_test( ], ) +grpc_cc_test( + name = "ssl_credentials_test", + srcs = ["ssl_credentials_test.c"], + language = "C", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ] +) + grpc_cc_binary( name = "create_jwt", srcs = ["create_jwt.c"], diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c index 34f310142c..72618602e9 100644 --- a/test/core/security/credentials_test.c +++ b/test/core/security/credentials_test.c @@ -24,6 +24,8 @@ #include <stdlib.h> #include <string.h> +#include <grpc/slice.h> + #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/string_util.h> @@ -35,6 +37,7 @@ #include "src/core/lib/security/credentials/google_default/google_default_credentials.h" #include "src/core/lib/security/credentials/jwt/jwt_credentials.h" #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" +#include "src/core/lib/security/transport/auth_filters.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #include "src/core/lib/support/tmpfile.h" @@ -1178,6 +1181,77 @@ static void test_channel_creds_duplicate_without_call_creds(void) { grpc_exec_ctx_finish(&exec_ctx); } +typedef struct { + const char *url_scheme; + const char *call_host; + const char *call_method; + const char *desired_service_url; + const char *desired_method_name; +} auth_metadata_context_test_case; + +static void test_auth_metadata_context(void) { + auth_metadata_context_test_case test_cases[] = { + // No service nor method. + {"https", "www.foo.com", "", "https://www.foo.com", ""}, + // No method. + {"https", "www.foo.com", "/Service", "https://www.foo.com/Service", ""}, + // Empty service and method. + {"https", "www.foo.com", "//", "https://www.foo.com/", ""}, + // Empty method. + {"https", "www.foo.com", "/Service/", "https://www.foo.com/Service", ""}, + // Malformed url. + {"https", "www.foo.com:", "/Service/", "https://www.foo.com:/Service", + ""}, + // https, default explicit port. + {"https", "www.foo.com:443", "/Service/FooMethod", + "https://www.foo.com/Service", "FooMethod"}, + // https, default implicit port. + {"https", "www.foo.com", "/Service/FooMethod", + "https://www.foo.com/Service", "FooMethod"}, + // https with ipv6 literal, default explicit port. + {"https", "[1080:0:0:0:8:800:200C:417A]:443", "/Service/FooMethod", + "https://[1080:0:0:0:8:800:200C:417A]/Service", "FooMethod"}, + // https with ipv6 literal, default implicit port. + {"https", "[1080:0:0:0:8:800:200C:443]", "/Service/FooMethod", + "https://[1080:0:0:0:8:800:200C:443]/Service", "FooMethod"}, + // https, custom port. + {"https", "www.foo.com:8888", "/Service/FooMethod", + "https://www.foo.com:8888/Service", "FooMethod"}, + // https with ipv6 literal, custom port. + {"https", "[1080:0:0:0:8:800:200C:417A]:8888", "/Service/FooMethod", + "https://[1080:0:0:0:8:800:200C:417A]:8888/Service", "FooMethod"}, + // custom url scheme, https default port. + {"blah", "www.foo.com:443", "/Service/FooMethod", + "blah://www.foo.com:443/Service", "FooMethod"}}; + for (uint32_t i = 0; i < GPR_ARRAY_SIZE(test_cases); i++) { + const char *url_scheme = test_cases[i].url_scheme; + grpc_slice call_host = + grpc_slice_from_copied_string(test_cases[i].call_host); + grpc_slice call_method = + grpc_slice_from_copied_string(test_cases[i].call_method); + grpc_auth_metadata_context auth_md_context; + memset(&auth_md_context, 0, sizeof(auth_md_context)); + grpc_auth_metadata_context_build(url_scheme, call_host, call_method, NULL, + &auth_md_context); + if (strcmp(auth_md_context.service_url, + test_cases[i].desired_service_url) != 0) { + gpr_log(GPR_ERROR, "Invalid service url, want: %s, got %s.", + test_cases[i].desired_service_url, auth_md_context.service_url); + GPR_ASSERT(false); + } + if (strcmp(auth_md_context.method_name, + test_cases[i].desired_method_name) != 0) { + gpr_log(GPR_ERROR, "Invalid method name, want: %s, got %s.", + test_cases[i].desired_method_name, auth_md_context.method_name); + GPR_ASSERT(false); + } + GPR_ASSERT(auth_md_context.channel_auth_context == NULL); + grpc_slice_unref(call_host); + grpc_slice_unref(call_method); + grpc_auth_metadata_context_reset(&auth_md_context); + } +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); grpc_init(); @@ -1211,6 +1285,7 @@ int main(int argc, char **argv) { test_metadata_plugin_failure(); test_get_well_known_google_credentials_file_path(); test_channel_creds_duplicate_without_call_creds(); + test_auth_metadata_context(); grpc_shutdown(); return 0; } diff --git a/test/core/security/ssl_credentials_test.c b/test/core/security/ssl_credentials_test.c new file mode 100644 index 0000000000..3c838faa60 --- /dev/null +++ b/test/core/security/ssl_credentials_test.c @@ -0,0 +1,66 @@ +/* + * + * Copyright 2017 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 <stdio.h> +#include <string.h> + +#include <grpc/grpc_security.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> + +#include "src/core/lib/security/credentials/ssl/ssl_credentials.h" +#include "src/core/tsi/ssl_transport_security.h" +#include "test/core/util/test_config.h" + +static void test_convert_grpc_to_tsi_cert_pairs() { + grpc_ssl_pem_key_cert_pair grpc_pairs[] = {{"private_key1", "cert_chain1"}, + {"private_key2", "cert_chain2"}, + {"private_key3", "cert_chain3"}}; + const size_t num_pairs = 3; + + { + tsi_ssl_pem_key_cert_pair *tsi_pairs = + grpc_convert_grpc_to_tsi_cert_pairs(grpc_pairs, 0); + GPR_ASSERT(tsi_pairs == NULL); + } + + { + tsi_ssl_pem_key_cert_pair *tsi_pairs = + grpc_convert_grpc_to_tsi_cert_pairs(grpc_pairs, num_pairs); + + GPR_ASSERT(tsi_pairs != NULL); + for (size_t i = 0; i < num_pairs; i++) { + GPR_ASSERT(strncmp(grpc_pairs[i].private_key, tsi_pairs[i].private_key, + strlen(grpc_pairs[i].private_key)) == 0); + GPR_ASSERT(strncmp(grpc_pairs[i].cert_chain, tsi_pairs[i].cert_chain, + strlen(grpc_pairs[i].cert_chain)) == 0); + } + + grpc_tsi_ssl_pem_key_cert_pairs_destroy(tsi_pairs, num_pairs); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + + test_convert_grpc_to_tsi_cert_pairs(); + + grpc_shutdown(); + return 0; +} diff --git a/test/core/support/BUILD b/test/core/support/BUILD index 407c3eff7b..3bdc1c4186 100644 --- a/test/core/support/BUILD +++ b/test/core/support/BUILD @@ -197,3 +197,29 @@ grpc_cc_test( "//test/core/util:gpr_test_util", ], ) + +grpc_cc_test( + name = "memory_test", + srcs = ["memory_test.cc"], + language = "C++", + deps = [ + "//:grpc", + "//test/core/util:gpr_test_util", + ], + external_deps = [ + "gtest", + ], +) + +grpc_cc_test( + name = "vector_test", + srcs = ["vector_test.cc"], + language = "C++", + deps = [ + "//:grpc", + "//test/core/util:gpr_test_util", + ], + external_deps = [ + "gtest", + ], +) diff --git a/test/core/support/vector_test.cc b/test/core/support/vector_test.cc new file mode 100644 index 0000000000..aad9f3be90 --- /dev/null +++ b/test/core/support/vector_test.cc @@ -0,0 +1,42 @@ +/* + * + * Copyright 2017 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/support/vector.h" +#include <gtest/gtest.h> +#include "test/core/util/test_config.h" + +namespace grpc_core { +namespace testing { + +TEST(InlinedVectorTest, CreateAndIterate) { + InlinedVector<int, 1> v{1, 2, 3}; + int sum = 0; + for (auto i : v) { + sum += i; + } + EXPECT_EQ(6, sum); +} + +} // namespace testing +} // namespace grpc_core + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c index e6372a379c..e4e4c9f1b2 100644 --- a/test/core/surface/completion_queue_test.c +++ b/test/core/surface/completion_queue_test.c @@ -158,6 +158,80 @@ static void test_cq_end_op(void) { } } +static void test_cq_tls_cache_full(void) { + grpc_event ev; + grpc_completion_queue *cc; + grpc_cq_completion completion; + grpc_cq_polling_type polling_types[] = { + GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; + grpc_completion_queue_attributes attr; + grpc_exec_ctx init_exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_exec_ctx exec_ctx; + void *tag = create_test_tag(); + void *res_tag; + int ok; + + LOG_TEST("test_cq_tls_cache_full"); + + attr.version = 1; + attr.cq_completion_type = GRPC_CQ_NEXT; + for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) { + exec_ctx = init_exec_ctx; // Reset exec_ctx + attr.cq_polling_type = polling_types[i]; + cc = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, NULL); + + grpc_completion_queue_thread_local_cache_init(cc); + GPR_ASSERT(grpc_cq_begin_op(cc, tag)); + grpc_cq_end_op(&exec_ctx, cc, tag, GRPC_ERROR_NONE, + do_nothing_end_completion, NULL, &completion); + + ev = grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); + + GPR_ASSERT( + grpc_completion_queue_thread_local_cache_flush(cc, &res_tag, &ok) == 1); + GPR_ASSERT(res_tag == tag); + GPR_ASSERT(ok); + + ev = grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); + + shutdown_and_destroy(cc); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +static void test_cq_tls_cache_empty(void) { + grpc_completion_queue *cc; + grpc_cq_polling_type polling_types[] = { + GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; + grpc_completion_queue_attributes attr; + grpc_exec_ctx init_exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_exec_ctx exec_ctx; + void *res_tag; + int ok; + + LOG_TEST("test_cq_tls_cache_empty"); + + attr.version = 1; + attr.cq_completion_type = GRPC_CQ_NEXT; + for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) { + exec_ctx = init_exec_ctx; // Reset exec_ctx + attr.cq_polling_type = polling_types[i]; + cc = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, NULL); + + GPR_ASSERT( + grpc_completion_queue_thread_local_cache_flush(cc, &res_tag, &ok) == 0); + grpc_completion_queue_thread_local_cache_init(cc); + GPR_ASSERT( + grpc_completion_queue_thread_local_cache_flush(cc, &res_tag, &ok) == 0); + shutdown_and_destroy(cc); + grpc_exec_ctx_finish(&exec_ctx); + } +} + static void test_shutdown_then_next_polling(void) { grpc_cq_polling_type polling_types[] = { GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; @@ -300,6 +374,8 @@ int main(int argc, char **argv) { test_cq_end_op(); test_pluck(); test_pluck_after_shutdown(); + test_cq_tls_cache_full(); + test_cq_tls_cache_empty(); grpc_shutdown(); return 0; } diff --git a/test/core/surface/init_test.c b/test/core/surface/init_test.c index a9e80575af..b835a2a884 100644 --- a/test/core/surface/init_test.c +++ b/test/core/surface/init_test.c @@ -53,7 +53,7 @@ static void test_plugin() { } static void test_repeatedly() { - for (int i = 0; i < 100000; i++) { + for (int i = 0; i < 1000; i++) { grpc_init(); grpc_shutdown(); } diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 18e609132b..7d6a11b1fb 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -64,4 +64,292 @@ #include <grpc/support/useful.h> #include <grpc/support/workaround_list.h> -int main(int argc, char **argv) { return 0; } +#include <stdio.h> + +int main(int argc, char **argv) { + if(argc == 12345678) { + printf("%lx", (unsigned long) grpc_compression_algorithm_is_message); + printf("%lx", (unsigned long) grpc_compression_algorithm_is_stream); + printf("%lx", (unsigned long) grpc_compression_algorithm_parse); + printf("%lx", (unsigned long) grpc_compression_algorithm_name); + printf("%lx", (unsigned long) grpc_compression_algorithm_for_level); + printf("%lx", (unsigned long) grpc_compression_options_init); + printf("%lx", (unsigned long) grpc_compression_options_enable_algorithm); + printf("%lx", (unsigned long) grpc_compression_options_disable_algorithm); + printf("%lx", (unsigned long) grpc_compression_options_is_algorithm_enabled); + printf("%lx", (unsigned long) grpc_compression_algorithm_parse_ruby); + printf("%lx", (unsigned long) grpc_compression_algorithm_name_ruby); + printf("%lx", (unsigned long) grpc_metadata_array_init); + printf("%lx", (unsigned long) grpc_metadata_array_destroy); + printf("%lx", (unsigned long) grpc_call_details_init); + printf("%lx", (unsigned long) grpc_call_details_destroy); + printf("%lx", (unsigned long) grpc_register_plugin); + printf("%lx", (unsigned long) grpc_init); + printf("%lx", (unsigned long) grpc_shutdown); + printf("%lx", (unsigned long) grpc_version_string); + printf("%lx", (unsigned long) grpc_g_stands_for); + printf("%lx", (unsigned long) grpc_completion_queue_factory_lookup); + printf("%lx", (unsigned long) grpc_completion_queue_create_for_next); + printf("%lx", (unsigned long) grpc_completion_queue_create_for_pluck); + printf("%lx", (unsigned long) grpc_completion_queue_create); + printf("%lx", (unsigned long) grpc_completion_queue_next); + printf("%lx", (unsigned long) grpc_completion_queue_pluck); + printf("%lx", (unsigned long) grpc_completion_queue_shutdown); + printf("%lx", (unsigned long) grpc_completion_queue_destroy); + printf("%lx", (unsigned long) grpc_completion_queue_thread_local_cache_init); + printf("%lx", (unsigned long) grpc_completion_queue_thread_local_cache_flush); + printf("%lx", (unsigned long) grpc_alarm_create); + printf("%lx", (unsigned long) grpc_alarm_set); + printf("%lx", (unsigned long) grpc_alarm_cancel); + printf("%lx", (unsigned long) grpc_alarm_destroy); + printf("%lx", (unsigned long) grpc_channel_check_connectivity_state); + printf("%lx", (unsigned long) grpc_channel_num_external_connectivity_watchers); + printf("%lx", (unsigned long) grpc_channel_watch_connectivity_state); + printf("%lx", (unsigned long) grpc_channel_support_connectivity_watcher); + printf("%lx", (unsigned long) grpc_channel_create_call); + printf("%lx", (unsigned long) grpc_channel_ping); + printf("%lx", (unsigned long) grpc_channel_register_call); + printf("%lx", (unsigned long) grpc_channel_create_registered_call); + printf("%lx", (unsigned long) grpc_call_arena_alloc); + printf("%lx", (unsigned long) grpc_call_start_batch); + printf("%lx", (unsigned long) grpc_call_get_peer); + printf("%lx", (unsigned long) grpc_census_call_set_context); + printf("%lx", (unsigned long) grpc_census_call_get_context); + printf("%lx", (unsigned long) grpc_channel_get_target); + printf("%lx", (unsigned long) grpc_channel_get_info); + printf("%lx", (unsigned long) grpc_insecure_channel_create); + printf("%lx", (unsigned long) grpc_lame_client_channel_create); + printf("%lx", (unsigned long) grpc_channel_destroy); + printf("%lx", (unsigned long) grpc_call_cancel); + printf("%lx", (unsigned long) grpc_call_cancel_with_status); + printf("%lx", (unsigned long) grpc_call_ref); + printf("%lx", (unsigned long) grpc_call_unref); + printf("%lx", (unsigned long) grpc_server_request_call); + printf("%lx", (unsigned long) grpc_server_register_method); + printf("%lx", (unsigned long) grpc_server_request_registered_call); + printf("%lx", (unsigned long) grpc_server_create); + printf("%lx", (unsigned long) grpc_server_register_completion_queue); + printf("%lx", (unsigned long) grpc_server_add_insecure_http2_port); + printf("%lx", (unsigned long) grpc_server_start); + printf("%lx", (unsigned long) grpc_server_shutdown_and_notify); + printf("%lx", (unsigned long) grpc_server_cancel_all_calls); + printf("%lx", (unsigned long) grpc_server_destroy); + printf("%lx", (unsigned long) grpc_tracer_set_enabled); + printf("%lx", (unsigned long) grpc_header_key_is_legal); + printf("%lx", (unsigned long) grpc_header_nonbin_value_is_legal); + printf("%lx", (unsigned long) grpc_is_binary_header); + printf("%lx", (unsigned long) grpc_call_error_to_string); + printf("%lx", (unsigned long) grpc_resource_quota_create); + printf("%lx", (unsigned long) grpc_resource_quota_ref); + printf("%lx", (unsigned long) grpc_resource_quota_unref); + printf("%lx", (unsigned long) grpc_resource_quota_resize); + printf("%lx", (unsigned long) grpc_resource_quota_arg_vtable); + printf("%lx", (unsigned long) grpc_auth_property_iterator_next); + printf("%lx", (unsigned long) grpc_auth_context_property_iterator); + printf("%lx", (unsigned long) grpc_auth_context_peer_identity); + printf("%lx", (unsigned long) grpc_auth_context_find_properties_by_name); + printf("%lx", (unsigned long) grpc_auth_context_peer_identity_property_name); + printf("%lx", (unsigned long) grpc_auth_context_peer_is_authenticated); + printf("%lx", (unsigned long) grpc_call_auth_context); + printf("%lx", (unsigned long) grpc_auth_context_release); + printf("%lx", (unsigned long) grpc_auth_context_add_property); + printf("%lx", (unsigned long) grpc_auth_context_add_cstring_property); + printf("%lx", (unsigned long) grpc_auth_context_set_peer_identity_property_name); + printf("%lx", (unsigned long) grpc_channel_credentials_release); + printf("%lx", (unsigned long) grpc_google_default_credentials_create); + printf("%lx", (unsigned long) grpc_set_ssl_roots_override_callback); + printf("%lx", (unsigned long) grpc_ssl_credentials_create); + printf("%lx", (unsigned long) grpc_call_credentials_release); + printf("%lx", (unsigned long) grpc_composite_channel_credentials_create); + printf("%lx", (unsigned long) grpc_composite_call_credentials_create); + printf("%lx", (unsigned long) grpc_google_compute_engine_credentials_create); + printf("%lx", (unsigned long) grpc_max_auth_token_lifetime); + printf("%lx", (unsigned long) grpc_service_account_jwt_access_credentials_create); + printf("%lx", (unsigned long) grpc_google_refresh_token_credentials_create); + printf("%lx", (unsigned long) grpc_access_token_credentials_create); + printf("%lx", (unsigned long) grpc_google_iam_credentials_create); + printf("%lx", (unsigned long) grpc_metadata_credentials_create_from_plugin); + printf("%lx", (unsigned long) grpc_secure_channel_create); + printf("%lx", (unsigned long) grpc_server_credentials_release); + printf("%lx", (unsigned long) grpc_ssl_server_certificate_config_create); + printf("%lx", (unsigned long) grpc_ssl_server_certificate_config_destroy); + printf("%lx", (unsigned long) grpc_ssl_server_credentials_create); + printf("%lx", (unsigned long) grpc_ssl_server_credentials_create_ex); + printf("%lx", (unsigned long) grpc_ssl_server_credentials_create_options_using_config); + printf("%lx", (unsigned long) grpc_ssl_server_credentials_create_options_using_config_fetcher); + printf("%lx", (unsigned long) grpc_ssl_server_credentials_options_destroy); + printf("%lx", (unsigned long) grpc_ssl_server_credentials_create_with_options); + printf("%lx", (unsigned long) grpc_server_add_secure_http2_port); + printf("%lx", (unsigned long) grpc_call_set_credentials); + printf("%lx", (unsigned long) grpc_server_credentials_set_auth_metadata_processor); + printf("%lx", (unsigned long) grpc_raw_byte_buffer_create); + printf("%lx", (unsigned long) grpc_raw_compressed_byte_buffer_create); + printf("%lx", (unsigned long) grpc_byte_buffer_copy); + printf("%lx", (unsigned long) grpc_byte_buffer_length); + printf("%lx", (unsigned long) grpc_byte_buffer_destroy); + printf("%lx", (unsigned long) grpc_byte_buffer_reader_init); + printf("%lx", (unsigned long) grpc_byte_buffer_reader_destroy); + printf("%lx", (unsigned long) grpc_byte_buffer_reader_next); + printf("%lx", (unsigned long) grpc_byte_buffer_reader_readall); + printf("%lx", (unsigned long) grpc_raw_byte_buffer_from_reader); + printf("%lx", (unsigned long) grpc_slice_ref); + printf("%lx", (unsigned long) grpc_slice_unref); + printf("%lx", (unsigned long) grpc_slice_copy); + printf("%lx", (unsigned long) grpc_slice_new); + printf("%lx", (unsigned long) grpc_slice_new_with_user_data); + printf("%lx", (unsigned long) grpc_slice_new_with_len); + printf("%lx", (unsigned long) grpc_slice_malloc); + printf("%lx", (unsigned long) grpc_slice_malloc_large); + printf("%lx", (unsigned long) grpc_slice_intern); + printf("%lx", (unsigned long) grpc_slice_from_copied_string); + printf("%lx", (unsigned long) grpc_slice_from_copied_buffer); + printf("%lx", (unsigned long) grpc_slice_from_static_string); + printf("%lx", (unsigned long) grpc_slice_from_static_buffer); + printf("%lx", (unsigned long) grpc_slice_sub); + printf("%lx", (unsigned long) grpc_slice_sub_no_ref); + printf("%lx", (unsigned long) grpc_slice_split_tail); + printf("%lx", (unsigned long) grpc_slice_split_tail_maybe_ref); + printf("%lx", (unsigned long) grpc_slice_split_head); + printf("%lx", (unsigned long) grpc_empty_slice); + printf("%lx", (unsigned long) grpc_slice_default_hash_impl); + printf("%lx", (unsigned long) grpc_slice_default_eq_impl); + printf("%lx", (unsigned long) grpc_slice_eq); + printf("%lx", (unsigned long) grpc_slice_cmp); + printf("%lx", (unsigned long) grpc_slice_str_cmp); + printf("%lx", (unsigned long) grpc_slice_buf_start_eq); + printf("%lx", (unsigned long) grpc_slice_rchr); + printf("%lx", (unsigned long) grpc_slice_chr); + printf("%lx", (unsigned long) grpc_slice_slice); + printf("%lx", (unsigned long) grpc_slice_hash); + printf("%lx", (unsigned long) grpc_slice_is_equivalent); + printf("%lx", (unsigned long) grpc_slice_dup); + printf("%lx", (unsigned long) grpc_slice_to_c_string); + printf("%lx", (unsigned long) grpc_slice_buffer_init); + printf("%lx", (unsigned long) grpc_slice_buffer_destroy); + printf("%lx", (unsigned long) grpc_slice_buffer_add); + printf("%lx", (unsigned long) grpc_slice_buffer_add_indexed); + printf("%lx", (unsigned long) grpc_slice_buffer_addn); + printf("%lx", (unsigned long) grpc_slice_buffer_tiny_add); + printf("%lx", (unsigned long) grpc_slice_buffer_pop); + printf("%lx", (unsigned long) grpc_slice_buffer_reset_and_unref); + printf("%lx", (unsigned long) grpc_slice_buffer_swap); + printf("%lx", (unsigned long) grpc_slice_buffer_move_into); + printf("%lx", (unsigned long) grpc_slice_buffer_trim_end); + printf("%lx", (unsigned long) grpc_slice_buffer_move_first); + printf("%lx", (unsigned long) grpc_slice_buffer_move_first_no_ref); + printf("%lx", (unsigned long) grpc_slice_buffer_move_first_into_buffer); + printf("%lx", (unsigned long) grpc_slice_buffer_take_first); + printf("%lx", (unsigned long) grpc_slice_buffer_undo_take_first); + printf("%lx", (unsigned long) gpr_malloc); + printf("%lx", (unsigned long) gpr_zalloc); + printf("%lx", (unsigned long) gpr_free); + printf("%lx", (unsigned long) gpr_realloc); + printf("%lx", (unsigned long) gpr_malloc_aligned); + printf("%lx", (unsigned long) gpr_free_aligned); + printf("%lx", (unsigned long) gpr_set_allocation_functions); + printf("%lx", (unsigned long) gpr_get_allocation_functions); + printf("%lx", (unsigned long) gpr_avl_create); + printf("%lx", (unsigned long) gpr_avl_ref); + printf("%lx", (unsigned long) gpr_avl_unref); + printf("%lx", (unsigned long) gpr_avl_add); + printf("%lx", (unsigned long) gpr_avl_remove); + printf("%lx", (unsigned long) gpr_avl_get); + printf("%lx", (unsigned long) gpr_avl_maybe_get); + printf("%lx", (unsigned long) gpr_avl_is_empty); + printf("%lx", (unsigned long) gpr_cmdline_create); + printf("%lx", (unsigned long) gpr_cmdline_add_int); + printf("%lx", (unsigned long) gpr_cmdline_add_flag); + printf("%lx", (unsigned long) gpr_cmdline_add_string); + printf("%lx", (unsigned long) gpr_cmdline_on_extra_arg); + printf("%lx", (unsigned long) gpr_cmdline_set_survive_failure); + printf("%lx", (unsigned long) gpr_cmdline_parse); + printf("%lx", (unsigned long) gpr_cmdline_destroy); + printf("%lx", (unsigned long) gpr_cmdline_usage_string); + printf("%lx", (unsigned long) gpr_cpu_num_cores); + printf("%lx", (unsigned long) gpr_cpu_current_cpu); + printf("%lx", (unsigned long) gpr_histogram_create); + printf("%lx", (unsigned long) gpr_histogram_destroy); + printf("%lx", (unsigned long) gpr_histogram_add); + printf("%lx", (unsigned long) gpr_histogram_merge); + printf("%lx", (unsigned long) gpr_histogram_percentile); + printf("%lx", (unsigned long) gpr_histogram_mean); + printf("%lx", (unsigned long) gpr_histogram_stddev); + printf("%lx", (unsigned long) gpr_histogram_variance); + printf("%lx", (unsigned long) gpr_histogram_maximum); + printf("%lx", (unsigned long) gpr_histogram_minimum); + printf("%lx", (unsigned long) gpr_histogram_count); + printf("%lx", (unsigned long) gpr_histogram_sum); + printf("%lx", (unsigned long) gpr_histogram_sum_of_squares); + printf("%lx", (unsigned long) gpr_histogram_get_contents); + printf("%lx", (unsigned long) gpr_histogram_merge_contents); + printf("%lx", (unsigned long) gpr_join_host_port); + printf("%lx", (unsigned long) gpr_split_host_port); + printf("%lx", (unsigned long) gpr_log_severity_string); + printf("%lx", (unsigned long) gpr_log); + printf("%lx", (unsigned long) gpr_log_message); + printf("%lx", (unsigned long) gpr_set_log_verbosity); + printf("%lx", (unsigned long) gpr_log_verbosity_init); + printf("%lx", (unsigned long) gpr_set_log_function); + printf("%lx", (unsigned long) gpr_strdup); + printf("%lx", (unsigned long) gpr_asprintf); + printf("%lx", (unsigned long) gpr_subprocess_binary_extension); + printf("%lx", (unsigned long) gpr_subprocess_create); + printf("%lx", (unsigned long) gpr_subprocess_destroy); + printf("%lx", (unsigned long) gpr_subprocess_join); + printf("%lx", (unsigned long) gpr_subprocess_interrupt); + printf("%lx", (unsigned long) gpr_mu_init); + printf("%lx", (unsigned long) gpr_mu_destroy); + printf("%lx", (unsigned long) gpr_mu_lock); + printf("%lx", (unsigned long) gpr_mu_unlock); + printf("%lx", (unsigned long) gpr_mu_trylock); + printf("%lx", (unsigned long) gpr_cv_init); + printf("%lx", (unsigned long) gpr_cv_destroy); + printf("%lx", (unsigned long) gpr_cv_wait); + printf("%lx", (unsigned long) gpr_cv_signal); + printf("%lx", (unsigned long) gpr_cv_broadcast); + printf("%lx", (unsigned long) gpr_once_init); + printf("%lx", (unsigned long) gpr_event_init); + printf("%lx", (unsigned long) gpr_event_set); + printf("%lx", (unsigned long) gpr_event_get); + printf("%lx", (unsigned long) gpr_event_wait); + printf("%lx", (unsigned long) gpr_ref_init); + printf("%lx", (unsigned long) gpr_ref); + printf("%lx", (unsigned long) gpr_ref_non_zero); + printf("%lx", (unsigned long) gpr_refn); + printf("%lx", (unsigned long) gpr_unref); + printf("%lx", (unsigned long) gpr_ref_is_unique); + printf("%lx", (unsigned long) gpr_stats_init); + printf("%lx", (unsigned long) gpr_stats_inc); + printf("%lx", (unsigned long) gpr_stats_read); + printf("%lx", (unsigned long) gpr_thd_new); + printf("%lx", (unsigned long) gpr_thd_options_default); + printf("%lx", (unsigned long) gpr_thd_options_set_detached); + printf("%lx", (unsigned long) gpr_thd_options_set_joinable); + printf("%lx", (unsigned long) gpr_thd_options_is_detached); + printf("%lx", (unsigned long) gpr_thd_options_is_joinable); + printf("%lx", (unsigned long) gpr_thd_currentid); + printf("%lx", (unsigned long) gpr_thd_join); + printf("%lx", (unsigned long) gpr_time_0); + printf("%lx", (unsigned long) gpr_inf_future); + printf("%lx", (unsigned long) gpr_inf_past); + printf("%lx", (unsigned long) gpr_time_init); + printf("%lx", (unsigned long) gpr_now); + printf("%lx", (unsigned long) gpr_convert_clock_type); + printf("%lx", (unsigned long) gpr_time_cmp); + printf("%lx", (unsigned long) gpr_time_max); + printf("%lx", (unsigned long) gpr_time_min); + printf("%lx", (unsigned long) gpr_time_add); + printf("%lx", (unsigned long) gpr_time_sub); + printf("%lx", (unsigned long) gpr_time_from_micros); + printf("%lx", (unsigned long) gpr_time_from_nanos); + printf("%lx", (unsigned long) gpr_time_from_millis); + printf("%lx", (unsigned long) gpr_time_from_seconds); + printf("%lx", (unsigned long) gpr_time_from_minutes); + printf("%lx", (unsigned long) gpr_time_from_hours); + printf("%lx", (unsigned long) gpr_time_to_millis); + printf("%lx", (unsigned long) gpr_time_similar); + printf("%lx", (unsigned long) gpr_sleep_until); + printf("%lx", (unsigned long) gpr_timespec_to_micros); + } + return 0; +} diff --git a/test/core/transport/BUILD b/test/core/transport/BUILD index 12e36132c8..edd27b8a5f 100644 --- a/test/core/transport/BUILD +++ b/test/core/transport/BUILD @@ -20,14 +20,17 @@ grpc_package(name = "test/core/transport") grpc_cc_test( name = "bdp_estimator_test", - srcs = ["bdp_estimator_test.c"], - language = "C", + srcs = ["bdp_estimator_test.cc"], + language = "C++", deps = [ "//:gpr", "//:grpc", "//test/core/util:gpr_test_util", "//test/core/util:grpc_test_util", ], + external_deps = [ + "gtest", + ], ) grpc_cc_test( @@ -68,14 +71,17 @@ grpc_cc_test( grpc_cc_test( name = "pid_controller_test", - srcs = ["pid_controller_test.c"], - language = "C", + srcs = ["pid_controller_test.cc"], + language = "C++", deps = [ "//:gpr", "//:grpc", "//test/core/util:gpr_test_util", "//test/core/util:grpc_test_util", ], + external_deps = [ + "gtest", + ], ) grpc_cc_test( diff --git a/test/core/transport/bdp_estimator_test.c b/test/core/transport/bdp_estimator_test.c deleted file mode 100644 index 4912ad5887..0000000000 --- a/test/core/transport/bdp_estimator_test.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * - * Copyright 2016 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/bdp_estimator.h" - -#include <grpc/grpc.h> -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/string_util.h> -#include <grpc/support/useful.h> -#include <limits.h> -#include "src/core/lib/iomgr/timer_manager.h" -#include "src/core/lib/support/string.h" -#include "test/core/util/test_config.h" - -extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type); - -static int g_clock = 0; - -static gpr_timespec fake_gpr_now(gpr_clock_type clock_type) { - return (gpr_timespec){ - .tv_sec = g_clock, .tv_nsec = 0, .clock_type = clock_type, - }; -} - -static void inc_time(void) { g_clock += 30; } - -static void test_noop(void) { - gpr_log(GPR_INFO, "test_noop"); - grpc_bdp_estimator est; - grpc_bdp_estimator_init(&est, "test"); -} - -static void test_get_estimate_no_samples(void) { - gpr_log(GPR_INFO, "test_get_estimate_no_samples"); - grpc_bdp_estimator est; - grpc_bdp_estimator_init(&est, "test"); - int64_t estimate; - grpc_bdp_estimator_get_estimate(&est, &estimate); -} - -static void add_samples(grpc_bdp_estimator *estimator, int64_t *samples, - size_t n) { - grpc_bdp_estimator_add_incoming_bytes(estimator, 1234567); - inc_time(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GPR_ASSERT(grpc_bdp_estimator_need_ping(&exec_ctx, estimator) == true); - grpc_bdp_estimator_schedule_ping(estimator); - grpc_bdp_estimator_start_ping(estimator); - for (size_t i = 0; i < n; i++) { - grpc_bdp_estimator_add_incoming_bytes(estimator, samples[i]); - GPR_ASSERT(grpc_bdp_estimator_need_ping(&exec_ctx, estimator) == false); - } - gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_millis(1, GPR_TIMESPAN))); - grpc_bdp_estimator_complete_ping(&exec_ctx, estimator); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void add_sample(grpc_bdp_estimator *estimator, int64_t sample) { - add_samples(estimator, &sample, 1); -} - -static void test_get_estimate_1_sample(void) { - gpr_log(GPR_INFO, "test_get_estimate_1_sample"); - grpc_bdp_estimator est; - grpc_bdp_estimator_init(&est, "test"); - add_sample(&est, 100); - int64_t estimate; - grpc_bdp_estimator_get_estimate(&est, &estimate); -} - -static void test_get_estimate_2_samples(void) { - gpr_log(GPR_INFO, "test_get_estimate_2_samples"); - grpc_bdp_estimator est; - grpc_bdp_estimator_init(&est, "test"); - add_sample(&est, 100); - add_sample(&est, 100); - int64_t estimate; - grpc_bdp_estimator_get_estimate(&est, &estimate); -} - -static int64_t get_estimate(grpc_bdp_estimator *estimator) { - int64_t out; - GPR_ASSERT(grpc_bdp_estimator_get_estimate(estimator, &out)); - return out; -} - -static void test_get_estimate_3_samples(void) { - gpr_log(GPR_INFO, "test_get_estimate_3_samples"); - grpc_bdp_estimator est; - grpc_bdp_estimator_init(&est, "test"); - add_sample(&est, 100); - add_sample(&est, 100); - add_sample(&est, 100); - int64_t estimate; - grpc_bdp_estimator_get_estimate(&est, &estimate); -} - -static int64_t next_pow_2(int64_t v) { - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v |= v >> 32; - v++; - return v; -} - -static void test_get_estimate_random_values(size_t n) { - gpr_log(GPR_INFO, "test_get_estimate_random_values(%" PRIdPTR ")", n); - grpc_bdp_estimator est; - grpc_bdp_estimator_init(&est, "test"); - const int kMaxSample = 65535; - int min = kMaxSample; - int max = 0; - for (size_t i = 0; i < n; i++) { - int sample = rand() % (kMaxSample + 1); - if (sample < min) min = sample; - if (sample > max) max = sample; - add_sample(&est, sample); - if (i >= 3) { - gpr_log(GPR_DEBUG, "est:%" PRId64 " min:%d max:%d", get_estimate(&est), - min, max); - GPR_ASSERT(get_estimate(&est) <= GPR_MAX(65536, 2 * next_pow_2(max))); - } - } -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - gpr_now_impl = fake_gpr_now; - grpc_init(); - grpc_timer_manager_set_threading(false); - test_noop(); - test_get_estimate_no_samples(); - test_get_estimate_1_sample(); - test_get_estimate_2_samples(); - test_get_estimate_3_samples(); - for (size_t i = 3; i < 1000; i = i * 3 / 2) { - test_get_estimate_random_values(i); - } - grpc_shutdown(); - return 0; -} diff --git a/test/core/transport/bdp_estimator_test.cc b/test/core/transport/bdp_estimator_test.cc new file mode 100644 index 0000000000..2c4fc4588b --- /dev/null +++ b/test/core/transport/bdp_estimator_test.cc @@ -0,0 +1,149 @@ +/* + * + * Copyright 2016 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/bdp_estimator.h" + +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/useful.h> +#include <gtest/gtest.h> +#include <limits.h> +#include "src/core/lib/iomgr/timer_manager.h" +#include "src/core/lib/support/string.h" +#include "test/core/util/test_config.h" + +extern "C" gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type); + +namespace grpc_core { +namespace testing { +namespace { +int g_clock = 0; + +gpr_timespec fake_gpr_now(gpr_clock_type clock_type) { + gpr_timespec ts; + ts.tv_sec = g_clock; + ts.tv_nsec = 0; + ts.clock_type = clock_type; + return ts; +} + +void inc_time(void) { g_clock += 30; } +} // namespace + +TEST(BdpEstimatorTest, NoOp) { BdpEstimator est("test"); } + +TEST(BdpEstimatorTest, EstimateBdpNoSamples) { + BdpEstimator est("test"); + est.EstimateBdp(); +} + +namespace { +void AddSamples(BdpEstimator *estimator, int64_t *samples, size_t n) { + estimator->AddIncomingBytes(1234567); + inc_time(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + estimator->SchedulePing(); + estimator->StartPing(); + for (size_t i = 0; i < n; i++) { + estimator->AddIncomingBytes(samples[i]); + } + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_millis(1, GPR_TIMESPAN))); + grpc_exec_ctx_invalidate_now(&exec_ctx); + estimator->CompletePing(&exec_ctx); + grpc_exec_ctx_finish(&exec_ctx); +} + +void AddSample(BdpEstimator *estimator, int64_t sample) { + AddSamples(estimator, &sample, 1); +} +} // namespace + +TEST(BdpEstimatorTest, GetEstimate1Sample) { + BdpEstimator est("test"); + AddSample(&est, 100); + est.EstimateBdp(); +} + +TEST(BdpEstimatorTest, GetEstimate2Samples) { + BdpEstimator est("test"); + AddSample(&est, 100); + AddSample(&est, 100); + est.EstimateBdp(); +} + +TEST(BdpEstimatorTest, GetEstimate3Samples) { + BdpEstimator est("test"); + AddSample(&est, 100); + AddSample(&est, 100); + AddSample(&est, 100); + est.EstimateBdp(); +} + +namespace { +int64_t NextPow2(int64_t v) { + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v |= v >> 32; + v++; + return v; +} +} // namespace + +class BdpEstimatorRandomTest : public ::testing::TestWithParam<size_t> {}; + +TEST_P(BdpEstimatorRandomTest, GetEstimateRandomValues) { + BdpEstimator est("test"); + const int kMaxSample = 65535; + int min = kMaxSample; + int max = 0; + for (size_t i = 0; i < GetParam(); i++) { + int sample = rand() % (kMaxSample + 1); + if (sample < min) min = sample; + if (sample > max) max = sample; + AddSample(&est, sample); + if (i >= 3) { + EXPECT_LE(est.EstimateBdp(), GPR_MAX(65536, 2 * NextPow2(max))) + << " min:" << min << " max:" << max << " sample:" << sample; + } + } +} + +INSTANTIATE_TEST_CASE_P(TooManyNames, BdpEstimatorRandomTest, + ::testing::Values(3, 4, 6, 9, 13, 19, 28, 42, 63, 94, + 141, 211, 316, 474, 711)); + +} // namespace testing +} // namespace grpc_core + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + gpr_now_impl = grpc_core::testing::fake_gpr_now; + grpc_init(); + grpc_timer_manager_set_threading(false); + ::testing::InitGoogleTest(&argc, argv); + int ret = RUN_ALL_TESTS(); + grpc_shutdown(); + return ret; +} diff --git a/test/core/transport/chttp2/hpack_encoder_test.c b/test/core/transport/chttp2/hpack_encoder_test.c index ed51dd1859..a2af83b6cb 100644 --- a/test/core/transport/chttp2/hpack_encoder_test.c +++ b/test/core/transport/chttp2/hpack_encoder_test.c @@ -43,10 +43,15 @@ void **to_delete = NULL; size_t num_to_delete = 0; size_t cap_to_delete = 0; +typedef struct { + bool eof; + bool use_true_binary_metadata; + bool only_intern_key; +} verify_params; + /* verify that the output generated by encoding the stream matches the hexstring passed in */ -static void verify(grpc_exec_ctx *exec_ctx, size_t window_available, bool eof, - bool use_true_binary_metadata, size_t expect_window_used, +static void verify(grpc_exec_ctx *exec_ctx, const verify_params params, const char *expected, size_t nheaders, ...) { grpc_slice_buffer output; grpc_slice merged; @@ -66,9 +71,13 @@ static void verify(grpc_exec_ctx *exec_ctx, size_t window_available, bool eof, e[i - 1].next = &e[i]; e[i].prev = &e[i - 1]; } + grpc_slice value_slice = grpc_slice_from_static_string(value); + if (!params.only_intern_key) { + value_slice = grpc_slice_intern(value_slice); + } e[i].md = grpc_mdelem_from_slices( exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(key)), - grpc_slice_intern(grpc_slice_from_static_string(value))); + value_slice); } e[0].prev = NULL; e[nheaders - 1].next = NULL; @@ -90,8 +99,8 @@ static void verify(grpc_exec_ctx *exec_ctx, size_t window_available, bool eof, memset(&stats, 0, sizeof(stats)); grpc_encode_header_options hopt = { .stream_id = 0xdeadbeef, - .is_eof = eof, - .use_true_binary_metadata = use_true_binary_metadata, + .is_eof = params.eof, + .use_true_binary_metadata = params.use_true_binary_metadata, .max_frame_size = 16384, .stats = &stats, }; @@ -119,28 +128,27 @@ static void verify(grpc_exec_ctx *exec_ctx, size_t window_available, bool eof, static void test_basic_headers(grpc_exec_ctx *exec_ctx) { int i; - verify(exec_ctx, 0, false, false, 0, "000005 0104 deadbeef 40 0161 0161", 1, - "a", "a"); - verify(exec_ctx, 0, false, false, 0, "000001 0104 deadbeef be", 1, "a", "a"); - verify(exec_ctx, 0, false, false, 0, "000001 0104 deadbeef be", 1, "a", "a"); - verify(exec_ctx, 0, false, false, 0, "000006 0104 deadbeef be 40 0162 0163", - 2, "a", "a", "b", "c"); - verify(exec_ctx, 0, false, false, 0, "000002 0104 deadbeef bf be", 2, "a", - "a", "b", "c"); - verify(exec_ctx, 0, false, false, 0, "000004 0104 deadbeef 7f 00 0164", 1, - "a", "d"); + verify_params params = { + .eof = false, .use_true_binary_metadata = false, .only_intern_key = false, + }; + verify(exec_ctx, params, "000005 0104 deadbeef 40 0161 0161", 1, "a", "a"); + verify(exec_ctx, params, "000001 0104 deadbeef be", 1, "a", "a"); + verify(exec_ctx, params, "000001 0104 deadbeef be", 1, "a", "a"); + verify(exec_ctx, params, "000006 0104 deadbeef be 40 0162 0163", 2, "a", "a", + "b", "c"); + verify(exec_ctx, params, "000002 0104 deadbeef bf be", 2, "a", "a", "b", "c"); + verify(exec_ctx, params, "000004 0104 deadbeef 7f 00 0164", 1, "a", "d"); /* flush out what's there to make a few values look very popular */ for (i = 0; i < 350; i++) { - verify(exec_ctx, 0, false, false, 0, "000003 0104 deadbeef c0 bf be", 3, - "a", "a", "b", "c", "a", "d"); + verify(exec_ctx, params, "000003 0104 deadbeef c0 bf be", 3, "a", "a", "b", + "c", "a", "d"); } - verify(exec_ctx, 0, false, false, 0, "000006 0104 deadbeef c0 00 016b 0176", - 2, "a", "a", "k", "v"); + verify(exec_ctx, params, "000006 0104 deadbeef c0 00 016b 0176", 2, "a", "a", + "k", "v"); /* this could be 000004 0104 deadbeef 0f 30 0176 also */ - verify(exec_ctx, 0, false, false, 0, "000004 0104 deadbeef 0f 2f 0176", 1, - "a", "v"); + verify(exec_ctx, params, "000004 0104 deadbeef 0f 2f 0176", 1, "a", "v"); } static void encode_int_to_str(int i, char *p) { @@ -156,6 +164,10 @@ static void test_decode_table_overflow(grpc_exec_ctx *exec_ctx) { char key[3], value[3]; char *expect; + verify_params params = { + .eof = false, .use_true_binary_metadata = false, .only_intern_key = false, + }; + for (i = 0; i < 114; i++) { encode_int_to_str(i, key); encode_int_to_str(i + 1, value); @@ -174,27 +186,28 @@ static void test_decode_table_overflow(grpc_exec_ctx *exec_ctx) { } if (i > 0) { - verify(exec_ctx, 0, false, false, 0, expect, 2, "aa", "ba", key, value); + verify(exec_ctx, params, expect, 2, "aa", "ba", key, value); } else { - verify(exec_ctx, 0, false, false, 0, expect, 1, key, value); + verify(exec_ctx, params, expect, 1, key, value); } gpr_free(expect); } /* if the above passes, then we must have just knocked this pair out of the decoder stack, and so we'll be forced to re-encode it */ - verify(exec_ctx, 0, false, false, 0, "000007 0104 deadbeef 40 026161 026261", - 1, "aa", "ba"); + verify(exec_ctx, params, "000007 0104 deadbeef 40 026161 026261", 1, "aa", + "ba"); } static void verify_table_size_change_match_elem_size(grpc_exec_ctx *exec_ctx, const char *key, - const char *value) { + const char *value, + bool use_true_binary) { grpc_slice_buffer output; grpc_mdelem elem = grpc_mdelem_from_slices( exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(key)), grpc_slice_intern(grpc_slice_from_static_string(value))); - size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem); + size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem, use_true_binary); size_t initial_table_size = g_compressor.table_size; grpc_linked_mdelem *e = gpr_malloc(sizeof(*e)); grpc_metadata_batch b; @@ -209,11 +222,12 @@ static void verify_table_size_change_match_elem_size(grpc_exec_ctx *exec_ctx, grpc_transport_one_way_stats stats; memset(&stats, 0, sizeof(stats)); - grpc_encode_header_options hopt = {.stream_id = 0xdeadbeef, - .is_eof = false, - .use_true_binary_metadata = false, - .max_frame_size = 16384, - .stats = &stats}; + grpc_encode_header_options hopt = { + .stream_id = 0xdeadbeef, + .is_eof = false, + .use_true_binary_metadata = use_true_binary, + .max_frame_size = 16384, + .stats = &stats}; grpc_chttp2_encode_header(exec_ctx, &g_compressor, NULL, 0, &b, &hopt, &output); grpc_slice_buffer_destroy_internal(exec_ctx, &output); @@ -224,8 +238,24 @@ static void verify_table_size_change_match_elem_size(grpc_exec_ctx *exec_ctx, } static void test_encode_header_size(grpc_exec_ctx *exec_ctx) { - verify_table_size_change_match_elem_size(exec_ctx, "hello", "world"); - verify_table_size_change_match_elem_size(exec_ctx, "hello-bin", "world"); + verify_table_size_change_match_elem_size(exec_ctx, "hello", "world", false); + verify_table_size_change_match_elem_size(exec_ctx, "hello-bin", "world", + false); + verify_table_size_change_match_elem_size(exec_ctx, "true-binary-bin", + "I_am_true_binary_value", true); +} + +static void test_interned_key_indexed(grpc_exec_ctx *exec_ctx) { + int i; + verify_params params = { + .eof = false, .use_true_binary_metadata = false, .only_intern_key = true, + }; + verify(exec_ctx, params, "000009 0104 deadbeef 40 0161 0162 0f2f 0163", 2, + "a", "b", "a", "c"); + for (i = 0; i < 10; i++) { + verify(exec_ctx, params, "000008 0104 deadbeef 0f2f 0162 0f2f 0163", 2, "a", + "b", "a", "c"); + } } static void run_test(void (*test)(grpc_exec_ctx *exec_ctx), const char *name) { @@ -245,6 +275,7 @@ int main(int argc, char **argv) { TEST(test_basic_headers); TEST(test_decode_table_overflow); TEST(test_encode_header_size); + TEST(test_interned_key_indexed); grpc_shutdown(); for (i = 0; i < num_to_delete; i++) { gpr_free(to_delete[i]); diff --git a/test/core/transport/metadata_test.c b/test/core/transport/metadata_test.c index cb06fce30b..f7124d29a7 100644 --- a/test/core/transport/metadata_test.c +++ b/test/core/transport/metadata_test.c @@ -302,7 +302,7 @@ static void verify_ascii_header_size(grpc_exec_ctx *exec_ctx, const char *key, grpc_mdelem elem = grpc_mdelem_from_slices( exec_ctx, 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); + 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(exec_ctx, elem); @@ -316,7 +316,7 @@ static void verify_binary_header_size(grpc_exec_ctx *exec_ctx, const char *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); + 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); diff --git a/test/core/transport/pid_controller_test.c b/test/core/transport/pid_controller_test.c deleted file mode 100644 index 831c4b41ce..0000000000 --- a/test/core/transport/pid_controller_test.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * Copyright 2016 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/pid_controller.h" - -#include <float.h> -#include <math.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/string_util.h> -#include <grpc/support/useful.h> -#include "src/core/lib/support/string.h" -#include "test/core/util/test_config.h" - -static void test_noop(void) { - gpr_log(GPR_INFO, "test_noop"); - grpc_pid_controller pid; - grpc_pid_controller_init( - &pid, (grpc_pid_controller_args){.gain_p = 1, - .gain_i = 1, - .gain_d = 1, - .initial_control_value = 1, - .min_control_value = DBL_MIN, - .max_control_value = DBL_MAX, - .integral_range = DBL_MAX}); -} - -static void test_simple_convergence(double gain_p, double gain_i, double gain_d, - double dt, double set_point, double start) { - gpr_log(GPR_INFO, - "test_simple_convergence(p=%lf, i=%lf, d=%lf); dt=%lf set_point=%lf " - "start=%lf", - gain_p, gain_i, gain_d, dt, set_point, start); - grpc_pid_controller pid; - grpc_pid_controller_init( - &pid, (grpc_pid_controller_args){.gain_p = gain_p, - .gain_i = gain_i, - .gain_d = gain_d, - .initial_control_value = start, - .min_control_value = DBL_MIN, - .max_control_value = DBL_MAX, - .integral_range = DBL_MAX}); - - for (int i = 0; i < 100000; i++) { - grpc_pid_controller_update(&pid, set_point - grpc_pid_controller_last(&pid), - 1); - } - - GPR_ASSERT(fabs(set_point - grpc_pid_controller_last(&pid)) < 0.1); - if (gain_i > 0) { - GPR_ASSERT(fabs(pid.error_integral) < 0.1); - } -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_noop(); - test_simple_convergence(0.2, 0, 0, 1, 100, 0); - test_simple_convergence(0.2, 0.1, 0, 1, 100, 0); - test_simple_convergence(0.2, 0.1, 0.1, 1, 100, 0); - return 0; -} diff --git a/test/core/transport/pid_controller_test.cc b/test/core/transport/pid_controller_test.cc new file mode 100644 index 0000000000..081d03472a --- /dev/null +++ b/test/core/transport/pid_controller_test.cc @@ -0,0 +1,91 @@ +/* + * + * Copyright 2016 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/pid_controller.h" + +#include <float.h> +#include <math.h> + +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/useful.h> +#include <gtest/gtest.h> +#include "src/core/lib/support/string.h" +#include "test/core/util/test_config.h" + +namespace grpc_core { +namespace testing { + +TEST(PidController, NoOp) { + PidController pid(PidController::Args() + .set_gain_p(1) + .set_gain_i(1) + .set_gain_d(1) + .set_initial_control_value(1)); +} + +struct SimpleConvergenceTestArgs { + double gain_p; + double gain_i; + double gain_d; + double dt; + double set_point; + double start; +}; + +std::ostream& operator<<(std::ostream& out, SimpleConvergenceTestArgs args) { + return out << "gain_p:" << args.gain_p << " gain_i:" << args.gain_i + << " gain_d:" << args.gain_d << " dt:" << args.dt + << " set_point:" << args.set_point << " start:" << args.start; +} + +class SimpleConvergenceTest + : public ::testing::TestWithParam<SimpleConvergenceTestArgs> {}; + +TEST_P(SimpleConvergenceTest, Converges) { + PidController pid(PidController::Args() + .set_gain_p(GetParam().gain_p) + .set_gain_i(GetParam().gain_i) + .set_gain_d(GetParam().gain_d) + .set_initial_control_value(GetParam().start)); + + for (int i = 0; i < 100000; i++) { + pid.Update(GetParam().set_point - pid.last_control_value(), GetParam().dt); + } + + EXPECT_LT(fabs(GetParam().set_point - pid.last_control_value()), 0.1); + if (GetParam().gain_i > 0) { + EXPECT_LT(fabs(pid.error_integral()), 0.1); + } +} + +INSTANTIATE_TEST_CASE_P( + X, SimpleConvergenceTest, + ::testing::Values(SimpleConvergenceTestArgs{0.2, 0, 0, 1, 100, 0}, + SimpleConvergenceTestArgs{0.2, 0.1, 0, 1, 100, 0}, + SimpleConvergenceTestArgs{0.2, 0.1, 0.1, 1, 100, 0})); + +} // namespace testing +} // namespace grpc_core + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/core/transport/status_conversion_test.c b/test/core/transport/status_conversion_test.c index de8fa4458a..02dad86693 100644 --- a/test/core/transport/status_conversion_test.c +++ b/test/core/transport/status_conversion_test.c @@ -38,6 +38,7 @@ int main(int argc, char **argv) { int i; grpc_test_init(argc, argv); + grpc_init(); GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_OK, GRPC_HTTP2_NO_ERROR); GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_CANCELLED, GRPC_HTTP2_CANCEL); @@ -129,6 +130,11 @@ int main(int argc, char **argv) { GRPC_STATUS_INTERNAL); HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_REFUSED_STREAM, after_deadline, GRPC_STATUS_UNAVAILABLE); + // We only have millisecond granularity in our timing code. This sleeps for 5 + // millis to ensure that the status conversion code will pick up the fact + // that the deadline has expired. + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_millis(5, GPR_TIMESPAN))); HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CANCEL, after_deadline, GRPC_STATUS_DEADLINE_EXCEEDED); HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_COMPRESSION_ERROR, after_deadline, @@ -158,5 +164,7 @@ int main(int argc, char **argv) { grpc_http2_status_to_grpc_status(i); } + grpc_shutdown(); + return 0; } diff --git a/test/core/transport/timeout_encoding_test.c b/test/core/transport/timeout_encoding_test.c index 3010c6d057..30357faed3 100644 --- a/test/core/transport/timeout_encoding_test.c +++ b/test/core/transport/timeout_encoding_test.c @@ -102,18 +102,20 @@ void decode_suite(char ext, grpc_millis (*answer)(int64_t x)) { } static grpc_millis millis_from_nanos(int64_t x) { - return x / GPR_NS_PER_MS + (x % GPR_NS_PER_MS != 0); + return (grpc_millis)(x / GPR_NS_PER_MS + (x % GPR_NS_PER_MS != 0)); } static grpc_millis millis_from_micros(int64_t x) { - return x / GPR_US_PER_MS + (x % GPR_US_PER_MS != 0); + return (grpc_millis)(x / GPR_US_PER_MS + (x % GPR_US_PER_MS != 0)); +} +static grpc_millis millis_from_millis(int64_t x) { return (grpc_millis)x; } +static grpc_millis millis_from_seconds(int64_t x) { + return (grpc_millis)(x * GPR_MS_PER_SEC); } -static grpc_millis millis_from_millis(int64_t x) { return x; } -static grpc_millis millis_from_seconds(int64_t x) { return x * GPR_MS_PER_SEC; } static grpc_millis millis_from_minutes(int64_t x) { - return x * 60 * GPR_MS_PER_SEC; + return (grpc_millis)(x * 60 * GPR_MS_PER_SEC); } static grpc_millis millis_from_hours(int64_t x) { - return x * 3600 * GPR_MS_PER_SEC; + return (grpc_millis)(x * 3600 * GPR_MS_PER_SEC); } void test_decoding(void) { diff --git a/test/core/tsi/transport_security_test_lib.c b/test/core/tsi/transport_security_test_lib.c index 329b2371bf..1f32eab21c 100644 --- a/test/core/tsi/transport_security_test_lib.c +++ b/test/core/tsi/transport_security_test_lib.c @@ -350,25 +350,28 @@ static void do_handshaker_next(handshaker_args *args) { tsi_handshaker_result *handshaker_result = NULL; unsigned char *bytes_to_send = NULL; size_t bytes_to_send_size = 0; + tsi_result result = TSI_OK; /* Receive data from peer, if available. */ - size_t buf_size = args->handshake_buffer_size; - receive_bytes_from_peer(args->fixture, &args->handshake_buffer, &buf_size, - args->is_client); - if (buf_size > 0) { - args->transferred_data = true; - } - /* Peform handshaker next. */ - tsi_result result = tsi_handshaker_next( - handshaker, args->handshake_buffer, buf_size, - (const unsigned char **)&bytes_to_send, &bytes_to_send_size, - &handshaker_result, &on_handshake_next_done_wrapper, args); - if (result != TSI_ASYNC) { - args->error = on_handshake_next_done(result, args, bytes_to_send, - bytes_to_send_size, handshaker_result); - if (args->error != GRPC_ERROR_NONE) { - return; + do { + size_t buf_size = args->handshake_buffer_size; + receive_bytes_from_peer(args->fixture, &args->handshake_buffer, &buf_size, + args->is_client); + if (buf_size > 0) { + args->transferred_data = true; } - } + /* Peform handshaker next. */ + result = tsi_handshaker_next(handshaker, args->handshake_buffer, buf_size, + (const unsigned char **)&bytes_to_send, + &bytes_to_send_size, &handshaker_result, + &on_handshake_next_done_wrapper, args); + if (result != TSI_ASYNC) { + args->error = on_handshake_next_done( + result, args, bytes_to_send, bytes_to_send_size, handshaker_result); + if (args->error != GRPC_ERROR_NONE) { + return; + } + } + } while (result == TSI_INCOMPLETE_DATA); notification_wait(fixture); } diff --git a/test/core/tsi/transport_security_test_lib.h b/test/core/tsi/transport_security_test_lib.h index ed8ff856df..74f4378bc1 100644 --- a/test/core/tsi/transport_security_test_lib.h +++ b/test/core/tsi/transport_security_test_lib.h @@ -21,6 +21,8 @@ #include "src/core/tsi/transport_security_interface.h" +#include <grpc/support/sync.h> + #ifdef __cplusplus extern "C" { #endif diff --git a/test/core/util/BUILD b/test/core/util/BUILD index abb50a0c99..5844a17728 100644 --- a/test/core/util/BUILD +++ b/test/core/util/BUILD @@ -32,9 +32,22 @@ grpc_cc_library( ) grpc_cc_library( + name = "grpc_debugger_macros", + srcs = [ + "debugger_macros.cc", + ], + hdrs = [ + "debugger_macros.h", + ], + deps = [ + ":gpr_test_util", + "//:grpc_common", + ], +) + +grpc_cc_library( name = "grpc_test_util_base", srcs = [ - "debugger_macros.c", "grpc_profiler.c", "mock_endpoint.c", "parse_hexstring.c", @@ -47,7 +60,6 @@ grpc_cc_library( "trickle_endpoint.c", ], hdrs = [ - "debugger_macros.h", "grpc_profiler.h", "mock_endpoint.h", "parse_hexstring.h", @@ -63,6 +75,7 @@ grpc_cc_library( deps = [ ":gpr_test_util", "//:grpc_common", + ":grpc_debugger_macros" ], ) diff --git a/test/core/util/debugger_macros.c b/test/core/util/debugger_macros.cc index ebe74f1fd6..72384f2dd7 100644 --- a/test/core/util/debugger_macros.c +++ b/test/core/util/debugger_macros.cc @@ -29,7 +29,7 @@ #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/surface/call.h" -void grpc_summon_debugger_macros() {} +extern "C" void grpc_summon_debugger_macros() {} grpc_stream *grpc_transport_stream_from_call(grpc_call *call) { grpc_call_stack *cs = grpc_call_get_call_stack(call); diff --git a/test/core/util/debugger_macros.h b/test/core/util/debugger_macros.h index c6b3720c5a..24718d9307 100644 --- a/test/core/util/debugger_macros.h +++ b/test/core/util/debugger_macros.h @@ -19,6 +19,14 @@ #ifndef GRPC_TEST_CORE_UTIL_DEBUGGER_MACROS_H #define GRPC_TEST_CORE_UTIL_DEBUGGER_MACROS_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + void grpc_summon_debugger_macros(); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + #endif /* GRPC_TEST_CORE_UTIL_DEBUGGER_MACROS_H */ diff --git a/test/core/util/mock_endpoint.c b/test/core/util/mock_endpoint.c index bd386b2148..7cae5c045e 100644 --- a/test/core/util/mock_endpoint.c +++ b/test/core/util/mock_endpoint.c @@ -69,6 +69,10 @@ static void me_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, static void me_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset_set *pollset) {} +static void me_delete_from_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_endpoint *ep, + grpc_pollset_set *pollset) {} + static void me_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_error *why) { grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep; @@ -103,8 +107,15 @@ static grpc_resource_user *me_get_resource_user(grpc_endpoint *ep) { static int me_get_fd(grpc_endpoint *ep) { return -1; } static const grpc_endpoint_vtable vtable = { - me_read, me_write, me_add_to_pollset, me_add_to_pollset_set, - me_shutdown, me_destroy, me_get_resource_user, me_get_peer, + me_read, + me_write, + me_add_to_pollset, + me_add_to_pollset_set, + me_delete_from_pollset_set, + me_shutdown, + me_destroy, + me_get_resource_user, + me_get_peer, me_get_fd, }; diff --git a/test/core/util/passthru_endpoint.c b/test/core/util/passthru_endpoint.c index 38a47584d5..ed39255294 100644 --- a/test/core/util/passthru_endpoint.c +++ b/test/core/util/passthru_endpoint.c @@ -82,7 +82,7 @@ static void me_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, half *m = other_half((half *)ep); gpr_mu_lock(&m->parent->mu); grpc_error *error = GRPC_ERROR_NONE; - m->parent->stats->num_writes++; + gpr_atm_no_barrier_fetch_add(&m->parent->stats->num_writes, (gpr_atm)1); if (m->parent->shutdown) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Endpoint already shutdown"); } else if (m->on_read != NULL) { @@ -107,6 +107,10 @@ static void me_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, static void me_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset_set *pollset) {} +static void me_delete_from_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_endpoint *ep, + grpc_pollset_set *pollset) {} + static void me_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_error *why) { half *m = (half *)ep; @@ -160,8 +164,15 @@ static grpc_resource_user *me_get_resource_user(grpc_endpoint *ep) { } static const grpc_endpoint_vtable vtable = { - me_read, me_write, me_add_to_pollset, me_add_to_pollset_set, - me_shutdown, me_destroy, me_get_resource_user, me_get_peer, + me_read, + me_write, + me_add_to_pollset, + me_add_to_pollset_set, + me_delete_from_pollset_set, + me_shutdown, + me_destroy, + me_get_resource_user, + me_get_peer, me_get_fd, }; diff --git a/test/core/util/passthru_endpoint.h b/test/core/util/passthru_endpoint.h index da769024a5..23d21c6061 100644 --- a/test/core/util/passthru_endpoint.h +++ b/test/core/util/passthru_endpoint.h @@ -19,9 +19,11 @@ #ifndef MOCK_ENDPOINT_H #define MOCK_ENDPOINT_H +#include <grpc/support/atm.h> + #include "src/core/lib/iomgr/endpoint.h" -typedef struct { int num_writes; } grpc_passthru_endpoint_stats; +typedef struct { gpr_atm num_writes; } grpc_passthru_endpoint_stats; void grpc_passthru_endpoint_create(grpc_endpoint **client, grpc_endpoint **server, diff --git a/test/core/util/trickle_endpoint.c b/test/core/util/trickle_endpoint.c index fc066f9d80..d761f72297 100644 --- a/test/core/util/trickle_endpoint.c +++ b/test/core/util/trickle_endpoint.c @@ -89,6 +89,13 @@ static void te_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_endpoint_add_to_pollset_set(exec_ctx, te->wrapped, pollset_set); } +static void te_delete_from_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_endpoint *ep, + grpc_pollset_set *pollset_set) { + trickle_endpoint *te = (trickle_endpoint *)ep; + grpc_endpoint_delete_from_pollset_set(exec_ctx, te->wrapped, pollset_set); +} + static void te_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_error *why) { trickle_endpoint *te = (trickle_endpoint *)ep; @@ -135,10 +142,16 @@ static void te_finish_write(grpc_exec_ctx *exec_ctx, void *arg, gpr_mu_unlock(&te->mu); } -static const grpc_endpoint_vtable vtable = { - te_read, te_write, te_add_to_pollset, te_add_to_pollset_set, - te_shutdown, te_destroy, te_get_resource_user, te_get_peer, - te_get_fd}; +static const grpc_endpoint_vtable vtable = {te_read, + te_write, + te_add_to_pollset, + te_add_to_pollset_set, + te_delete_from_pollset_set, + te_shutdown, + te_destroy, + te_get_resource_user, + te_get_peer, + te_get_fd}; grpc_endpoint *grpc_trickle_endpoint_create(grpc_endpoint *wrap, double bytes_per_second) { diff --git a/test/core/util/trickle_endpoint.h b/test/core/util/trickle_endpoint.h index 78f1eeeda2..ca39638ba0 100644 --- a/test/core/util/trickle_endpoint.h +++ b/test/core/util/trickle_endpoint.h @@ -21,6 +21,10 @@ #include "src/core/lib/iomgr/endpoint.h" +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + grpc_endpoint *grpc_trickle_endpoint_create(grpc_endpoint *wrap, double bytes_per_second); @@ -30,4 +34,8 @@ size_t grpc_trickle_endpoint_trickle(grpc_exec_ctx *exec_ctx, size_t grpc_trickle_get_backlog(grpc_endpoint *endpoint); +#ifdef __cplusplus +} +#endif // __cplusplus + #endif |