diff options
author | 2018-06-11 16:33:15 -0700 | |
---|---|---|
committer | 2018-06-11 16:33:15 -0700 | |
commit | dddf20793269a7ba5f658ae5fdcde2c175cf196b (patch) | |
tree | 595d0fbc0c501132857b63f00f073ec6a0f54f58 /test/core | |
parent | 935ae7d01242c21f0230ead18927087a70c03e5b (diff) | |
parent | 37b292a0f7500e434c9ae41919248e2641ddc7f1 (diff) |
Merge branch 'master' into epollerr
Diffstat (limited to 'test/core')
19 files changed, 1591 insertions, 16 deletions
diff --git a/test/core/end2end/end2end_nosec_tests.cc b/test/core/end2end/end2end_nosec_tests.cc index 59eb643a93..a70128254a 100644 --- a/test/core/end2end/end2end_nosec_tests.cc +++ b/test/core/end2end/end2end_nosec_tests.cc @@ -100,6 +100,8 @@ extern void negative_deadline(grpc_end2end_test_config config); extern void negative_deadline_pre_init(void); extern void network_status_change(grpc_end2end_test_config config); extern void network_status_change_pre_init(void); +extern void no_error_on_hotpath(grpc_end2end_test_config config); +extern void no_error_on_hotpath_pre_init(void); extern void no_logging(grpc_end2end_test_config config); extern void no_logging_pre_init(void); extern void no_op(grpc_end2end_test_config config); @@ -222,6 +224,7 @@ void grpc_end2end_tests_pre_init(void) { max_message_length_pre_init(); negative_deadline_pre_init(); network_status_change_pre_init(); + no_error_on_hotpath_pre_init(); no_logging_pre_init(); no_op_pre_init(); payload_pre_init(); @@ -307,6 +310,7 @@ void grpc_end2end_tests(int argc, char **argv, max_message_length(config); negative_deadline(config); network_status_change(config); + no_error_on_hotpath(config); no_logging(config); no_op(config); payload(config); @@ -492,6 +496,10 @@ void grpc_end2end_tests(int argc, char **argv, network_status_change(config); continue; } + if (0 == strcmp("no_error_on_hotpath", argv[i])) { + no_error_on_hotpath(config); + continue; + } if (0 == strcmp("no_logging", argv[i])) { no_logging(config); continue; diff --git a/test/core/end2end/end2end_tests.cc b/test/core/end2end/end2end_tests.cc index 9f164b4ead..bf75dd4579 100644 --- a/test/core/end2end/end2end_tests.cc +++ b/test/core/end2end/end2end_tests.cc @@ -102,6 +102,8 @@ extern void negative_deadline(grpc_end2end_test_config config); extern void negative_deadline_pre_init(void); extern void network_status_change(grpc_end2end_test_config config); extern void network_status_change_pre_init(void); +extern void no_error_on_hotpath(grpc_end2end_test_config config); +extern void no_error_on_hotpath_pre_init(void); extern void no_logging(grpc_end2end_test_config config); extern void no_logging_pre_init(void); extern void no_op(grpc_end2end_test_config config); @@ -225,6 +227,7 @@ void grpc_end2end_tests_pre_init(void) { max_message_length_pre_init(); negative_deadline_pre_init(); network_status_change_pre_init(); + no_error_on_hotpath_pre_init(); no_logging_pre_init(); no_op_pre_init(); payload_pre_init(); @@ -311,6 +314,7 @@ void grpc_end2end_tests(int argc, char **argv, max_message_length(config); negative_deadline(config); network_status_change(config); + no_error_on_hotpath(config); no_logging(config); no_op(config); payload(config); @@ -500,6 +504,10 @@ void grpc_end2end_tests(int argc, char **argv, network_status_change(config); continue; } + if (0 == strcmp("no_error_on_hotpath", argv[i])) { + no_error_on_hotpath(config); + continue; + } if (0 == strcmp("no_logging", argv[i])) { no_logging(config); continue; diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index c355fc24b5..1851214191 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -138,6 +138,7 @@ END2END_TESTS = { 'max_message_length': default_test_options._replace(cpu_cost=LOWCPU), 'negative_deadline': default_test_options, 'network_status_change': default_test_options._replace(cpu_cost=LOWCPU), + 'no_error_on_hotpath': default_test_options._replace(proxyable=False), 'no_logging': default_test_options._replace(traceable=False), 'no_op': default_test_options, 'payload': default_test_options, diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index 11fc576165..706f4fa86d 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -134,6 +134,7 @@ END2END_TESTS = { 'max_message_length': test_options(), 'negative_deadline': test_options(), 'network_status_change': test_options(), + 'no_error_on_hotpath': test_options(proxyable=False), 'no_logging': test_options(traceable=False), 'no_op': test_options(), 'payload': test_options(), diff --git a/test/core/end2end/tests/no_error_on_hotpath.cc b/test/core/end2end/tests/no_error_on_hotpath.cc new file mode 100644 index 0000000000..7afadf7d3a --- /dev/null +++ b/test/core/end2end/tests/no_error_on_hotpath.cc @@ -0,0 +1,246 @@ +/* + * + * 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 "test/core/end2end/end2end_tests.h" + +#include <stdio.h> +#include <string.h> + +#include <grpc/byte_buffer.h> +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/time.h> +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/iomgr/error.h" +#include "test/core/end2end/cq_verifier.h" + +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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue* cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture* f) { + if (!f->server) return; + grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000), + grpc_timeout_seconds_to_deadline(5), + nullptr) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(f->server); + f->server = nullptr; +} + +static void shutdown_client(grpc_end2end_test_fixture* f) { + if (!f->client) return; + grpc_channel_destroy(f->client); + f->client = nullptr; +} + +static void end_test(grpc_end2end_test_fixture* f) { + shutdown_server(f); + shutdown_client(f); + + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_request_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture f) { + grpc_call* c; + grpc_call* s; + cq_verifier* cqv = cq_verifier_create(f.cq); + grpc_op ops[6]; + grpc_op* op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + char* peer; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), nullptr, + deadline, nullptr); + GPR_ASSERT(c); + + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != nullptr); + gpr_free(peer); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->flags = 0; + op->reserved = nullptr; + op++; + error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1), + nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + error = + grpc_server_request_call(f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + cq_verify(cqv); + + peer = grpc_call_get_peer(s); + GPR_ASSERT(peer != nullptr); + gpr_free(peer); + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != nullptr); + gpr_free(peer); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status = GRPC_STATUS_OK; + op->data.send_status_from_server.status_details = nullptr; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = nullptr; + op++; + error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(102), + nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(102), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(GRPC_SLICE_LENGTH(details) == 0); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + GPR_ASSERT(0 == call_details.flags); + GPR_ASSERT(was_cancelled == 0); + + grpc_slice_unref(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + + grpc_call_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); +} + +static void test_no_error_on_hotpath_one_request( + grpc_end2end_test_config config) { + grpc_end2end_test_fixture f; + + f = begin_test(config, "test_invoke_simple_request_with_no_error_logging", + nullptr, nullptr); + // First RPC is not considered the hotpath, since there are lots of things to + // set up. + simple_request_body(config, f); + grpc_disable_error_creation(); + simple_request_body(config, f); + grpc_enable_error_creation(); + end_test(&f); + config.tear_down_data(&f); +} + +static void test_no_error_on_hotpath_10_requests( + grpc_end2end_test_config config) { + int i; + grpc_end2end_test_fixture f = begin_test( + config, "test_no_error_on_hotpath_in_one_request", nullptr, nullptr); + // First RPC is not considered the hotpath, since there are lots of things to + // set up. + simple_request_body(config, f); + grpc_disable_error_creation(); + for (i = 0; i < 10; i++) { + simple_request_body(config, f); + } + grpc_enable_error_creation(); + end_test(&f); + config.tear_down_data(&f); +} + +void no_error_on_hotpath(grpc_end2end_test_config config) { + test_no_error_on_hotpath_one_request(config); + test_no_error_on_hotpath_10_requests(config); +} + +void no_error_on_hotpath_pre_init(void) {} diff --git a/test/core/end2end/tests/retry_server_pushback_delay.cc b/test/core/end2end/tests/retry_server_pushback_delay.cc index f6a979613d..221b416828 100644 --- a/test/core/end2end/tests/retry_server_pushback_delay.cc +++ b/test/core/end2end/tests/retry_server_pushback_delay.cc @@ -249,7 +249,7 @@ static void test_retry_server_pushback_delay(grpc_end2end_test_config config) { retry_delay.tv_sec, retry_delay.tv_nsec); GPR_ASSERT(retry_delay.tv_sec >= 1); if (retry_delay.tv_sec == 1) { - GPR_ASSERT(retry_delay.tv_nsec >= 900000000); + GPR_ASSERT(retry_delay.tv_nsec >= 800000000); } peer = grpc_call_get_peer(s); diff --git a/test/core/gpr/arena_test.cc b/test/core/gpr/arena_test.cc index 111414ea3e..3e7c906591 100644 --- a/test/core/gpr/arena_test.cc +++ b/test/core/gpr/arena_test.cc @@ -71,7 +71,7 @@ static void test(const char* name, size_t init_size, const size_t* allocs, static const size_t allocs_##name[] = {__VA_ARGS__}; \ test(#name, init_size, allocs_##name, GPR_ARRAY_SIZE(allocs_##name)) -#define CONCURRENT_TEST_THREADS 100 +#define CONCURRENT_TEST_THREADS 10 size_t concurrent_test_iterations() { if (sizeof(void*) < 8) return 1000; diff --git a/test/core/iomgr/ios/CFStreamTests/CFStreamClientTests.mm b/test/core/iomgr/ios/CFStreamTests/CFStreamClientTests.mm new file mode 100644 index 0000000000..414b6c78c0 --- /dev/null +++ b/test/core/iomgr/ios/CFStreamTests/CFStreamClientTests.mm @@ -0,0 +1,201 @@ +/* + * + * Copyright 2018 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. + * + */ + +#import <XCTest/XCTest.h> + +#include "src/core/lib/iomgr/port.h" + +#ifdef GRPC_CFSTREAM + +#include <netinet/in.h> + +#include <grpc/impl/codegen/sync.h> +#include <grpc/support/sync.h> + +#include "src/core/lib/iomgr/endpoint.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/tcp_client.h" +#include "test/core/util/test_config.h" + +// static int g_connections_complete = 0; +static gpr_mu g_mu; +static int g_connections_complete = 0; +static grpc_endpoint* g_connecting = nullptr; + +static void finish_connection() { + gpr_mu_lock(&g_mu); + g_connections_complete++; + gpr_mu_unlock(&g_mu); +} + +static void must_succeed(void* arg, grpc_error* error) { + GPR_ASSERT(g_connecting != nullptr); + GPR_ASSERT(error == GRPC_ERROR_NONE); + grpc_endpoint_shutdown(g_connecting, GRPC_ERROR_CREATE_FROM_STATIC_STRING("must_succeed called")); + grpc_endpoint_destroy(g_connecting); + g_connecting = nullptr; + finish_connection(); +} + +static void must_fail(void* arg, grpc_error* error) { + GPR_ASSERT(g_connecting == nullptr); + GPR_ASSERT(error != GRPC_ERROR_NONE); + const char* error_str = grpc_error_string(error); + NSLog(@"%s", error_str); + finish_connection(); +} + +@interface CFStreamClientTests : XCTestCase + +@end + +@implementation CFStreamClientTests + ++ (void)setUp { + grpc_init(); + gpr_mu_init(&g_mu); +} + ++ (void)tearDown { + grpc_shutdown(); +} + +- (void)testSucceeds { + grpc_resolved_address resolved_addr; + struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr); + int svr_fd; + int r; + int connections_complete_before; + grpc_closure done; + grpc_core::ExecCtx exec_ctx; + + gpr_log(GPR_DEBUG, "test_succeeds"); + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + + /* create a dummy server */ + svr_fd = socket(AF_INET, SOCK_STREAM, 0); + GPR_ASSERT(svr_fd >= 0); + GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr.len)); + GPR_ASSERT(0 == listen(svr_fd, 1)); + + gpr_mu_lock(&g_mu); + connections_complete_before = g_connections_complete; + gpr_mu_unlock(&g_mu); + + /* connect to it */ + GPR_ASSERT(getsockname(svr_fd, (struct sockaddr*)addr, (socklen_t*)&resolved_addr.len) == 0); + GRPC_CLOSURE_INIT(&done, must_succeed, nullptr, grpc_schedule_on_exec_ctx); + grpc_tcp_client_connect(&done, &g_connecting, nullptr, nullptr, &resolved_addr, + GRPC_MILLIS_INF_FUTURE); + + /* await the connection */ + do { + resolved_addr.len = sizeof(addr); + r = accept(svr_fd, reinterpret_cast<struct sockaddr*>(addr), + reinterpret_cast<socklen_t*>(&resolved_addr.len)); + } while (r == -1 && errno == EINTR); + GPR_ASSERT(r >= 0); + close(r); + + grpc_core::ExecCtx::Get()->Flush(); + + /* wait for the connection callback to finish */ + gpr_mu_lock(&g_mu); + NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:5]; + while (connections_complete_before == g_connections_complete) { + gpr_mu_unlock(&g_mu); + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline]; + gpr_mu_lock(&g_mu); + } + XCTAssertGreaterThan(g_connections_complete, connections_complete_before); + + gpr_mu_unlock(&g_mu); +} + +- (void)testFails { + grpc_core::ExecCtx exec_ctx; + + grpc_resolved_address resolved_addr; + struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr); + int connections_complete_before; + grpc_closure done; + int svr_fd; + + gpr_log(GPR_DEBUG, "test_fails"); + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in)); + addr->sin_family = AF_INET; + + svr_fd = socket(AF_INET, SOCK_STREAM, 0); + GPR_ASSERT(svr_fd >= 0); + GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr.len)); + GPR_ASSERT(0 == listen(svr_fd, 1)); + GPR_ASSERT(getsockname(svr_fd, (struct sockaddr*)addr, (socklen_t*)&resolved_addr.len) == 0); + close(svr_fd); + + gpr_mu_lock(&g_mu); + connections_complete_before = g_connections_complete; + gpr_mu_unlock(&g_mu); + + /* connect to a broken address */ + GRPC_CLOSURE_INIT(&done, must_fail, nullptr, grpc_schedule_on_exec_ctx); + grpc_tcp_client_connect(&done, &g_connecting, nullptr, nullptr, &resolved_addr, + GRPC_MILLIS_INF_FUTURE); + + grpc_core::ExecCtx::Get()->Flush(); + + /* wait for the connection callback to finish */ + gpr_mu_lock(&g_mu); + NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:5]; + while (g_connections_complete == connections_complete_before) { + gpr_mu_unlock(&g_mu); + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline]; + gpr_mu_lock(&g_mu); + } + + XCTAssertGreaterThan(g_connections_complete, connections_complete_before); + + gpr_mu_unlock(&g_mu); +} + +@end + +#else // GRPC_CFSTREAM + +// Dummy test suite +@interface CFStreamClientTests : XCTestCase + +@end + +@implementation CFStreamClientTests + +- (void)setUp { + [super setUp]; +} + +- (void)tearDown { + [super tearDown]; +} + +@end + +#endif // GRPC_CFSTREAM diff --git a/test/core/iomgr/ios/CFStreamTests/CFStreamEndpointTests.mm b/test/core/iomgr/ios/CFStreamTests/CFStreamEndpointTests.mm new file mode 100644 index 0000000000..fbc34c74d6 --- /dev/null +++ b/test/core/iomgr/ios/CFStreamTests/CFStreamEndpointTests.mm @@ -0,0 +1,344 @@ +/* + * + * Copyright 2018 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. + * + */ + +#import <XCTest/XCTest.h> + +#include "src/core/lib/iomgr/port.h" + +#ifdef GRPC_CFSTREAM + +#include <netinet/in.h> + +#include <grpc/impl/codegen/sync.h> +#include <grpc/support/sync.h> + +#include "src/core/lib/iomgr/endpoint.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/tcp_client.h" +#include "test/core/util/test_config.h" + +static const int kConnectTimeout = 5; +static const int kWriteTimeout = 5; +static const int kReadTimeout = 5; + +static const int kBufferSize = 10000; + +static const int kRunLoopTimeout = 1; + +static void set_atm(void *arg, grpc_error *error) { + gpr_atm *p = static_cast<gpr_atm *>(arg); + gpr_atm_full_cas(p, -1, reinterpret_cast<gpr_atm>(error)); +} + +static void init_event_closure(grpc_closure *closure, gpr_atm *atm) { + *atm = -1; + GRPC_CLOSURE_INIT(closure, set_atm, static_cast<void *>(atm), grpc_schedule_on_exec_ctx); +} + +static bool compare_slice_buffer_with_buffer(grpc_slice_buffer *slices, const char *buffer, + size_t buffer_len) { + if (slices->length != buffer_len) { + return false; + } + + for (int i = 0; i < slices->count; i++) { + grpc_slice slice = slices->slices[i]; + if (0 != memcmp(buffer, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice))) { + return false; + } + buffer += GRPC_SLICE_LENGTH(slice); + } + + return true; +} + +@interface CFStreamEndpointTests : XCTestCase + +@end + +@implementation CFStreamEndpointTests { + grpc_endpoint *ep_; + int svr_fd_; +} + +- (BOOL)waitForEvent:(gpr_atm *)event timeout:(int)timeout { + grpc_core::ExecCtx::Get()->Flush(); + + NSDate *deadline = [NSDate dateWithTimeIntervalSinceNow:kConnectTimeout]; + while (gpr_atm_acq_load(event) == -1 && [deadline timeIntervalSinceNow] > 0) { + NSDate *deadline = [NSDate dateWithTimeIntervalSinceNow:kRunLoopTimeout]; + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline]; + } + + return (gpr_atm_acq_load(event) != -1); +} + ++ (void)setUp { + grpc_init(); +} + ++ (void)tearDown { + grpc_shutdown(); +} + +- (void)setUp { + self.continueAfterFailure = NO; + + // Set up CFStream connection before testing the endpoint + + grpc_core::ExecCtx exec_ctx; + + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = reinterpret_cast<struct sockaddr_in *>(resolved_addr.addr); + int svr_fd; + int r; + gpr_atm connected = -1; + grpc_closure done; + + gpr_log(GPR_DEBUG, "test_succeeds"); + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + + /* create a dummy server */ + svr_fd = socket(AF_INET, SOCK_STREAM, 0); + XCTAssertGreaterThanOrEqual(svr_fd, 0); + XCTAssertEqual(bind(svr_fd, (struct sockaddr *)addr, (socklen_t)resolved_addr.len), 0); + XCTAssertEqual(listen(svr_fd, 1), 0); + + /* connect to it */ + XCTAssertEqual(getsockname(svr_fd, (struct sockaddr *)addr, (socklen_t *)&resolved_addr.len), 0); + init_event_closure(&done, &connected); + grpc_tcp_client_connect(&done, &ep_, nullptr, nullptr, &resolved_addr, GRPC_MILLIS_INF_FUTURE); + + /* await the connection */ + do { + resolved_addr.len = sizeof(addr); + r = accept(svr_fd, reinterpret_cast<struct sockaddr *>(addr), + reinterpret_cast<socklen_t *>(&resolved_addr.len)); + } while (r == -1 && errno == EINTR); + XCTAssertGreaterThanOrEqual(r, 0); + svr_fd_ = r; + + /* wait for the connection callback to finish */ + XCTAssertEqual([self waitForEvent:&connected timeout:kConnectTimeout], YES); + XCTAssertEqual(reinterpret_cast<grpc_error *>(connected), GRPC_ERROR_NONE); +} + +- (void)tearDown { + grpc_core::ExecCtx exec_ctx; + close(svr_fd_); + grpc_endpoint_destroy(ep_); +} + +- (void)testReadWrite { + grpc_core::ExecCtx exec_ctx; + + gpr_atm read; + grpc_closure read_done; + grpc_slice_buffer read_slices; + grpc_slice_buffer read_one_slice; + gpr_atm write; + grpc_closure write_done; + grpc_slice_buffer write_slices; + + grpc_slice slice; + char write_buffer[kBufferSize]; + char read_buffer[kBufferSize]; + size_t recv_size = 0; + + grpc_slice_buffer_init(&write_slices); + slice = grpc_slice_from_static_buffer(write_buffer, kBufferSize); + grpc_slice_buffer_add(&write_slices, slice); + init_event_closure(&write_done, &write); + grpc_endpoint_write(ep_, &write_slices, &write_done); + + XCTAssertEqual([self waitForEvent:&write timeout:kWriteTimeout], YES); + XCTAssertEqual(reinterpret_cast<grpc_error *>(write), GRPC_ERROR_NONE); + + while (recv_size < kBufferSize) { + ssize_t size = recv(svr_fd_, read_buffer, kBufferSize, 0); + XCTAssertGreaterThanOrEqual(size, 0); + recv_size += size; + } + + XCTAssertEqual(recv_size, kBufferSize); + XCTAssertEqual(memcmp(read_buffer, write_buffer, kBufferSize), 0); + ssize_t send_size = send(svr_fd_, read_buffer, kBufferSize, 0); + XCTAssertGreaterThanOrEqual(send_size, 0); + + grpc_slice_buffer_init(&read_slices); + grpc_slice_buffer_init(&read_one_slice); + while (read_slices.length < kBufferSize) { + init_event_closure(&read_done, &read); + grpc_endpoint_read(ep_, &read_one_slice, &read_done); + XCTAssertEqual([self waitForEvent:&read timeout:kReadTimeout], YES); + XCTAssertEqual(reinterpret_cast<grpc_error *>(read), GRPC_ERROR_NONE); + grpc_slice_buffer_move_into(&read_one_slice, &read_slices); + XCTAssertLessThanOrEqual(read_slices.length, kBufferSize); + } + XCTAssertTrue(compare_slice_buffer_with_buffer(&read_slices, read_buffer, kBufferSize)); + + grpc_endpoint_shutdown(ep_, GRPC_ERROR_NONE); + grpc_slice_buffer_reset_and_unref(&read_slices); + grpc_slice_buffer_reset_and_unref(&write_slices); + grpc_slice_buffer_reset_and_unref(&read_one_slice); +} + +- (void)testShutdownBeforeRead { + grpc_core::ExecCtx exec_ctx; + + gpr_atm read; + grpc_closure read_done; + grpc_slice_buffer read_slices; + gpr_atm write; + grpc_closure write_done; + grpc_slice_buffer write_slices; + + grpc_slice slice; + char write_buffer[kBufferSize]; + char read_buffer[kBufferSize]; + size_t recv_size = 0; + + grpc_slice_buffer_init(&read_slices); + init_event_closure(&read_done, &read); + grpc_endpoint_read(ep_, &read_slices, &read_done); + + grpc_slice_buffer_init(&write_slices); + slice = grpc_slice_from_static_buffer(write_buffer, kBufferSize); + grpc_slice_buffer_add(&write_slices, slice); + init_event_closure(&write_done, &write); + grpc_endpoint_write(ep_, &write_slices, &write_done); + + XCTAssertEqual([self waitForEvent:&write timeout:kWriteTimeout], YES); + XCTAssertEqual(reinterpret_cast<grpc_error *>(write), GRPC_ERROR_NONE); + + while (recv_size < kBufferSize) { + ssize_t size = recv(svr_fd_, read_buffer, kBufferSize, 0); + XCTAssertGreaterThanOrEqual(size, 0); + recv_size += size; + } + + XCTAssertEqual(recv_size, kBufferSize); + XCTAssertEqual(memcmp(read_buffer, write_buffer, kBufferSize), 0); + + XCTAssertEqual([self waitForEvent:&read timeout:kReadTimeout], NO); + + grpc_endpoint_shutdown(ep_, GRPC_ERROR_NONE); + + grpc_core::ExecCtx::Get()->Flush(); + XCTAssertEqual([self waitForEvent:&read timeout:kReadTimeout], YES); + XCTAssertNotEqual(reinterpret_cast<grpc_error *>(read), GRPC_ERROR_NONE); + + grpc_slice_buffer_reset_and_unref(&read_slices); + grpc_slice_buffer_reset_and_unref(&write_slices); +} + +- (void)testRemoteClosed { + grpc_core::ExecCtx exec_ctx; + + gpr_atm read; + grpc_closure read_done; + grpc_slice_buffer read_slices; + gpr_atm write; + grpc_closure write_done; + grpc_slice_buffer write_slices; + + grpc_slice slice; + char write_buffer[kBufferSize]; + char read_buffer[kBufferSize]; + size_t recv_size = 0; + + init_event_closure(&read_done, &read); + grpc_slice_buffer_init(&read_slices); + grpc_endpoint_read(ep_, &read_slices, &read_done); + + grpc_slice_buffer_init(&write_slices); + slice = grpc_slice_from_static_buffer(write_buffer, kBufferSize); + grpc_slice_buffer_add(&write_slices, slice); + init_event_closure(&write_done, &write); + grpc_endpoint_write(ep_, &write_slices, &write_done); + + XCTAssertEqual([self waitForEvent:&write timeout:kWriteTimeout], YES); + XCTAssertEqual(reinterpret_cast<grpc_error *>(write), GRPC_ERROR_NONE); + + while (recv_size < kBufferSize) { + ssize_t size = recv(svr_fd_, read_buffer, kBufferSize, 0); + XCTAssertGreaterThanOrEqual(size, 0); + recv_size += size; + } + + XCTAssertEqual(recv_size, kBufferSize); + XCTAssertEqual(memcmp(read_buffer, write_buffer, kBufferSize), 0); + + close(svr_fd_); + + XCTAssertEqual([self waitForEvent:&read timeout:kReadTimeout], YES); + XCTAssertNotEqual(reinterpret_cast<grpc_error *>(read), GRPC_ERROR_NONE); + + grpc_endpoint_shutdown(ep_, GRPC_ERROR_NONE); + grpc_slice_buffer_reset_and_unref(&read_slices); + grpc_slice_buffer_reset_and_unref(&write_slices); +} + +- (void)testRemoteReset { + grpc_core::ExecCtx exec_ctx; + + gpr_atm read; + grpc_closure read_done; + grpc_slice_buffer read_slices; + + init_event_closure(&read_done, &read); + grpc_slice_buffer_init(&read_slices); + grpc_endpoint_read(ep_, &read_slices, &read_done); + + struct linger so_linger; + so_linger.l_onoff = 1; + so_linger.l_linger = 0; + setsockopt(svr_fd_, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger)); + + close(svr_fd_); + + XCTAssertEqual([self waitForEvent:&read timeout:kReadTimeout], YES); + XCTAssertNotEqual(reinterpret_cast<grpc_error *>(read), GRPC_ERROR_NONE); + + grpc_endpoint_shutdown(ep_, GRPC_ERROR_NONE); + grpc_slice_buffer_reset_and_unref(&read_slices); +} + +@end + +#else // GRPC_CFSTREAM + +// Dummy test suite +@interface CFStreamEndpointTests : XCTestCase +@end + +@implementation CFStreamEndpointTests +- (void)setUp { + [super setUp]; +} + +- (void)tearDown { + [super tearDown]; +} + +@end + +#endif // GRPC_CFSTREAM diff --git a/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/project.pbxproj b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..2218f129ae --- /dev/null +++ b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/project.pbxproj @@ -0,0 +1,338 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 48; + objects = { + +/* Begin PBXBuildFile section */ + 5E143B892069D72200715A6E /* CFStreamClientTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5E143B882069D72200715A6E /* CFStreamClientTests.mm */; }; + 5E143B8C206B5F9F00715A6E /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5E143B8A2069D72700715A6E /* Info.plist */; }; + 5E143B8E206C5B9A00715A6E /* CFStreamEndpointTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5E143B8D206C5B9A00715A6E /* CFStreamEndpointTests.mm */; }; + 604EA96D9CD477A8EA411BDF /* libPods-CFStreamTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AFFA154D492751CEAC05D591 /* libPods-CFStreamTests.a */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 5E143B792069D67300715A6E /* CFStreamTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CFStreamTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 5E143B882069D72200715A6E /* CFStreamClientTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CFStreamClientTests.mm; sourceTree = "<group>"; }; + 5E143B8A2069D72700715A6E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; + 5E143B8D206C5B9A00715A6E /* CFStreamEndpointTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CFStreamEndpointTests.mm; sourceTree = "<group>"; }; + 8CB4409E07E180CCA59987DF /* Pods-CFStreamTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CFStreamTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-CFStreamTests/Pods-CFStreamTests.release.xcconfig"; sourceTree = "<group>"; }; + 9E3FAF9DA6B98ED4FE6D6848 /* Pods-CFStreamTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CFStreamTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CFStreamTests/Pods-CFStreamTests.debug.xcconfig"; sourceTree = "<group>"; }; + AFFA154D492751CEAC05D591 /* libPods-CFStreamTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CFStreamTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 5E143B762069D67300715A6E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 604EA96D9CD477A8EA411BDF /* libPods-CFStreamTests.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 5E143B582069D67300715A6E = { + isa = PBXGroup; + children = ( + 5E143B8D206C5B9A00715A6E /* CFStreamEndpointTests.mm */, + 5E143B8A2069D72700715A6E /* Info.plist */, + 5E143B882069D72200715A6E /* CFStreamClientTests.mm */, + 5E143B622069D67300715A6E /* Products */, + A331D95F7F230B507FBF6D22 /* Pods */, + 6AC36F6C5DB5CA8F717D1B67 /* Frameworks */, + ); + sourceTree = "<group>"; + }; + 5E143B622069D67300715A6E /* Products */ = { + isa = PBXGroup; + children = ( + 5E143B792069D67300715A6E /* CFStreamTests.xctest */, + ); + name = Products; + sourceTree = "<group>"; + }; + 6AC36F6C5DB5CA8F717D1B67 /* Frameworks */ = { + isa = PBXGroup; + children = ( + AFFA154D492751CEAC05D591 /* libPods-CFStreamTests.a */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; + A331D95F7F230B507FBF6D22 /* Pods */ = { + isa = PBXGroup; + children = ( + 9E3FAF9DA6B98ED4FE6D6848 /* Pods-CFStreamTests.debug.xcconfig */, + 8CB4409E07E180CCA59987DF /* Pods-CFStreamTests.release.xcconfig */, + ); + name = Pods; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 5E143B782069D67300715A6E /* CFStreamTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5E143B852069D67300715A6E /* Build configuration list for PBXNativeTarget "CFStreamTests" */; + buildPhases = ( + 4EBA55D3E23FC6C84596E3D5 /* [CP] Check Pods Manifest.lock */, + 5E143B752069D67300715A6E /* Sources */, + 5E143B762069D67300715A6E /* Frameworks */, + 5E143B772069D67300715A6E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = CFStreamTests; + productName = CFStreamTestsTests; + productReference = 5E143B792069D67300715A6E /* CFStreamTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 5E143B592069D67300715A6E /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0920; + ORGANIZATIONNAME = gRPC; + TargetAttributes = { + 5E143B782069D67300715A6E = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 5E143B5C2069D67300715A6E /* Build configuration list for PBXProject "CFStreamTests" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 5E143B582069D67300715A6E; + productRefGroup = 5E143B622069D67300715A6E /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 5E143B782069D67300715A6E /* CFStreamTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 5E143B772069D67300715A6E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5E143B8C206B5F9F00715A6E /* Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 4EBA55D3E23FC6C84596E3D5 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-CFStreamTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5E143B752069D67300715A6E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5E143B892069D72200715A6E /* CFStreamClientTests.mm in Sources */, + 5E143B8E206C5B9A00715A6E /* CFStreamEndpointTests.mm in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 5E143B802069D67300715A6E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 5E143B812069D67300715A6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 5E143B862069D67300715A6E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9E3FAF9DA6B98ED4FE6D6848 /* Pods-CFStreamTests.debug.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "COCOAPODS=1", + "$(inherited)", + "PB_FIELD_32BIT=1", + "PB_NO_PACKED_STRUCTS=1", + "GRPC_CFSTREAM=1", + ); + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CFStreamTestsTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ../../../../..; + }; + name = Debug; + }; + 5E143B872069D67300715A6E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8CB4409E07E180CCA59987DF /* Pods-CFStreamTests.release.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CFStreamTestsTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ../../../../..; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 5E143B5C2069D67300715A6E /* Build configuration list for PBXProject "CFStreamTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5E143B802069D67300715A6E /* Debug */, + 5E143B812069D67300715A6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5E143B852069D67300715A6E /* Build configuration list for PBXNativeTarget "CFStreamTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5E143B862069D67300715A6E /* Debug */, + 5E143B872069D67300715A6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 5E143B592069D67300715A6E /* Project object */; +} diff --git a/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests.xcscheme b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests.xcscheme new file mode 100644 index 0000000000..25d6f780a1 --- /dev/null +++ b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests.xcscheme @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "0920" + version = "1.3"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES"> + </BuildAction> + <TestAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + shouldUseLaunchSchemeArgsEnv = "YES"> + <Testables> + <TestableReference + skipped = "NO"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "5E143B782069D67300715A6E" + BuildableName = "CFStreamTests.xctest" + BlueprintName = "CFStreamTests" + ReferencedContainer = "container:CFStreamTests.xcodeproj"> + </BuildableReference> + </TestableReference> + </Testables> + <AdditionalOptions> + </AdditionalOptions> + </TestAction> + <LaunchAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + debugServiceExtension = "internal" + allowLocationSimulation = "YES"> + <AdditionalOptions> + </AdditionalOptions> + </LaunchAction> + <ProfileAction + buildConfiguration = "Release" + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + debugDocumentVersioning = "YES"> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Debug"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Release" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Asan.xcscheme b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Asan.xcscheme new file mode 100644 index 0000000000..6c5c43aa72 --- /dev/null +++ b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Asan.xcscheme @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "0920" + version = "1.3"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES"> + </BuildAction> + <TestAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + enableAddressSanitizer = "YES" + enableASanStackUseAfterReturn = "YES" + language = "" + shouldUseLaunchSchemeArgsEnv = "YES"> + <Testables> + <TestableReference + skipped = "NO"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "5E143B782069D67300715A6E" + BuildableName = "CFStreamTests.xctest" + BlueprintName = "CFStreamTests" + ReferencedContainer = "container:CFStreamTests.xcodeproj"> + </BuildableReference> + </TestableReference> + </Testables> + <AdditionalOptions> + </AdditionalOptions> + </TestAction> + <LaunchAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + enableASanStackUseAfterReturn = "YES" + language = "" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + debugServiceExtension = "internal" + allowLocationSimulation = "YES"> + <AdditionalOptions> + </AdditionalOptions> + </LaunchAction> + <ProfileAction + buildConfiguration = "Release" + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + debugDocumentVersioning = "YES"> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Debug"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Release" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Msan.xcscheme b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Msan.xcscheme new file mode 100644 index 0000000000..3e39ff84d0 --- /dev/null +++ b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Msan.xcscheme @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "0920" + version = "1.3"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES"> + </BuildAction> + <TestAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" + shouldUseLaunchSchemeArgsEnv = "YES"> + <Testables> + <TestableReference + skipped = "NO"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "5E143B782069D67300715A6E" + BuildableName = "CFStreamTests.xctest" + BlueprintName = "CFStreamTests" + ReferencedContainer = "container:CFStreamTests.xcodeproj"> + </BuildableReference> + </TestableReference> + </Testables> + <AdditionalOptions> + <AdditionalOption + key = "DYLD_INSERT_LIBRARIES" + value = "/usr/lib/libgmalloc.dylib" + isEnabled = "YES"> + </AdditionalOption> + <AdditionalOption + key = "NSZombieEnabled" + value = "YES" + isEnabled = "YES"> + </AdditionalOption> + <AdditionalOption + key = "MallocGuardEdges" + value = "" + isEnabled = "YES"> + </AdditionalOption> + <AdditionalOption + key = "MallocScribble" + value = "" + isEnabled = "YES"> + </AdditionalOption> + </AdditionalOptions> + </TestAction> + <LaunchAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + debugServiceExtension = "internal" + allowLocationSimulation = "YES"> + <AdditionalOptions> + </AdditionalOptions> + </LaunchAction> + <ProfileAction + buildConfiguration = "Release" + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + debugDocumentVersioning = "YES"> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Debug"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Release" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Tsan.xcscheme b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Tsan.xcscheme new file mode 100644 index 0000000000..f0bde837c5 --- /dev/null +++ b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Tsan.xcscheme @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "0920" + version = "1.3"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES"> + </BuildAction> + <TestAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + enableThreadSanitizer = "YES" + language = "" + shouldUseLaunchSchemeArgsEnv = "YES"> + <Testables> + <TestableReference + skipped = "NO"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "5E143B782069D67300715A6E" + BuildableName = "CFStreamTests.xctest" + BlueprintName = "CFStreamTests" + ReferencedContainer = "container:CFStreamTests.xcodeproj"> + </BuildableReference> + </TestableReference> + </Testables> + <AdditionalOptions> + </AdditionalOptions> + </TestAction> + <LaunchAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + stopOnEveryThreadSanitizerIssue = "YES" + debugServiceExtension = "internal" + allowLocationSimulation = "YES"> + <AdditionalOptions> + </AdditionalOptions> + </LaunchAction> + <ProfileAction + buildConfiguration = "Release" + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + debugDocumentVersioning = "YES"> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Debug"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Release" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/test/core/iomgr/ios/CFStreamTests/Info.plist b/test/core/iomgr/ios/CFStreamTests/Info.plist new file mode 100644 index 0000000000..6c40a6cd0c --- /dev/null +++ b/test/core/iomgr/ios/CFStreamTests/Info.plist @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>$(DEVELOPMENT_LANGUAGE)</string> + <key>CFBundleExecutable</key> + <string>$(EXECUTABLE_NAME)</string> + <key>CFBundleIdentifier</key> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>$(PRODUCT_NAME)</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleVersion</key> + <string>1</string> +</dict> +</plist> diff --git a/test/core/iomgr/ios/CFStreamTests/Podfile b/test/core/iomgr/ios/CFStreamTests/Podfile new file mode 100644 index 0000000000..630168a363 --- /dev/null +++ b/test/core/iomgr/ios/CFStreamTests/Podfile @@ -0,0 +1,50 @@ +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '8.0' + +install! 'cocoapods', :deterministic_uuids => false + +# Location of gRPC's repo root relative to this file. +GRPC_LOCAL_SRC = '../../../../..' + +# Install the dependencies in the main target plus all test targets. +target 'CFStreamTests' do + pod 'gRPC-Core/CFStream-Implementation', :path => GRPC_LOCAL_SRC +end + +pre_install do |installer| + # This is the gRPC-Core podspec object, as initialized by its podspec file. + grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec + + # Copied from gRPC-Core.podspec, except for the adjusted src_root: + src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}" + grpc_core_spec.pod_target_xcconfig = { + 'GRPC_SRC_ROOT' => src_root, + 'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"', + 'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"', + # If we don't set these two settings, `include/grpc/support/time.h` and + # `src/core/lib/gpr/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the + # build. + 'USE_HEADERMAP' => 'NO', + 'ALWAYS_SEARCH_USER_PATHS' => 'NO', + } +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['GCC_TREAT_WARNINGS_AS_ERRORS'] = 'YES' + end + + # CocoaPods creates duplicated library targets of gRPC-Core when the test targets include + # non-default subspecs of gRPC-Core. All of these library targets start with prefix 'gRPC-Core' + # and require the same error suppresion. + if target.name.start_with?('gRPC-Core') + target.build_configurations.each do |config| + # TODO(zyc): Remove this setting after the issue is resolved + # GPR_UNREACHABLE_CODE causes "Control may reach end of non-void + # function" warning + config.build_settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'NO' + end + end + end +end diff --git a/test/core/iomgr/ios/CFStreamTests/build_tests.sh b/test/core/iomgr/ios/CFStreamTests/build_tests.sh new file mode 100755 index 0000000000..d23f26f5db --- /dev/null +++ b/test/core/iomgr/ios/CFStreamTests/build_tests.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright 2018 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. + +# Don't run this script standalone. Instead, run from the repository root: +# ./tools/run_tests/run_tests.py -l objc + +set -e + +# CocoaPods requires the terminal to be using UTF-8 encoding. +export LANG=en_US.UTF-8 + +cd "$(dirname "$0")" + +hash pod 2>/dev/null || { echo >&2 "Cocoapods needs to be installed."; exit 1; } +hash xcodebuild 2>/dev/null || { + echo >&2 "XCode command-line tools need to be installed." + exit 1 +} + +# clean the directory +rm -rf Pods +rm -rf CFStreamTests.xcworkspace +rm -f Podfile.lock + +echo "TIME: $(date)" +pod install + diff --git a/test/core/iomgr/ios/CFStreamTests/run_tests.sh b/test/core/iomgr/ios/CFStreamTests/run_tests.sh new file mode 100755 index 0000000000..1045ec10a8 --- /dev/null +++ b/test/core/iomgr/ios/CFStreamTests/run_tests.sh @@ -0,0 +1,67 @@ +#!/bin/bash +# Copyright 2018 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. + +# Don't run this script standalone. Instead, run from the repository root: +# ./tools/run_tests/run_tests.py -l objc + +set -ev + +cd "$(dirname "$0")" + +echo "TIME: $(date)" + +XCODEBUILD_FILTER='(^CompileC |^Ld |^ *[^ ]*clang |^ *cd |^ *export |^Libtool |^ *[^ ]*libtool |^CpHeader |^ *builtin-copy )' + +xcodebuild \ + -workspace CFStreamTests.xcworkspace \ + -scheme CFStreamTests \ + -destination name="iPhone 8" \ + test \ + | egrep -v "$XCODEBUILD_FILTER" \ + | egrep -v '^$' \ + | egrep -v "(GPBDictionary|GPBArray)" - + +echo "TIME: $(date)" + +xcodebuild \ + -workspace CFStreamTests.xcworkspace \ + -scheme CFStreamTests_Asan \ + -destination name="iPhone 8" \ + test \ + | egrep -v "$XCODEBUILD_FILTER" \ + | egrep -v '^$' \ + | egrep -v "(GPBDictionary|GPBArray)" - + +echo "TIME: $(date)" + +xcodebuild \ + -workspace CFStreamTests.xcworkspace \ + -scheme CFStreamTests_Tsan \ + -destination name="iPhone 8" \ + test \ + | egrep -v "$XCODEBUILD_FILTER" \ + | egrep -v '^$' \ + | egrep -v "(GPBDictionary|GPBArray)" - + +echo "TIME: $(date)" + +xcodebuild \ + -workspace CFStreamTests.xcworkspace \ + -scheme CFStreamTests_Msan \ + -destination name="iPhone 8" \ + test \ + | egrep -v "$XCODEBUILD_FILTER" \ + | egrep -v '^$' \ + | egrep -v "(GPBDictionary|GPBArray)" - diff --git a/test/core/transport/chttp2/hpack_encoder_test.cc b/test/core/transport/chttp2/hpack_encoder_test.cc index d3ba50a91c..2a57198ab6 100644 --- a/test/core/transport/chttp2/hpack_encoder_test.cc +++ b/test/core/transport/chttp2/hpack_encoder_test.cc @@ -160,6 +160,8 @@ static void encode_int_to_str(int i, char* p) { } static void test_decode_table_overflow() { + // Decrease the default table size to make decode table overflow easier. + grpc_chttp2_hpack_compressor_set_max_table_size(&g_compressor, 1024); int i; char key[3], value[3]; char* expect; @@ -170,27 +172,20 @@ static void test_decode_table_overflow() { false, }; - for (i = 0; i < 114; i++) { + for (i = 0; i < 29; i++) { encode_int_to_str(i, key); encode_int_to_str(i + 1, value); - - if (i + 61 >= 127) { + if (i == 0) { + // 3fe107 corresponds to the table size update. gpr_asprintf(&expect, - "000009 0104 deadbeef ff%02x 40 02%02x%02x 02%02x%02x", - i + 61 - 127, key[0], key[1], value[0], value[1]); - } else if (i > 0) { + "00000a 0104 deadbeef 3fe107 40 02%02x%02x 02%02x%02x", + key[0], key[1], value[0], value[1]); + verify(params, expect, 1, key, value); + } else { gpr_asprintf(&expect, "000008 0104 deadbeef %02x 40 02%02x%02x 02%02x%02x", 0x80 + 61 + i, key[0], key[1], value[0], value[1]); - } else { - gpr_asprintf(&expect, "000007 0104 deadbeef 40 02%02x%02x 02%02x%02x", - key[0], key[1], value[0], value[1]); - } - - if (i > 0) { verify(params, expect, 2, "aa", "ba", key, value); - } else { - verify(params, expect, 1, key, value); } gpr_free(expect); } |