Add test for handshake timeout.

pull/13336/head
Mark D. Roth 7 years ago
parent da6b4790e5
commit b9f34acfe5
  1. 40
      CMakeLists.txt
  2. 48
      Makefile
  3. 12
      build.yaml
  4. 12
      test/core/transport/chttp2/BUILD
  5. 258
      test/core/transport/chttp2/settings_timeout_test.cc
  6. 17
      tools/run_tests/generated/sources_and_headers.json
  7. 24
      tools/run_tests/generated/tests.json

@ -677,6 +677,7 @@ add_dependencies(buildtests_cxx bm_pollset)
endif()
add_dependencies(buildtests_cxx channel_arguments_test)
add_dependencies(buildtests_cxx channel_filter_test)
add_dependencies(buildtests_cxx chttp2_settings_timeout_test)
add_dependencies(buildtests_cxx cli_call_test)
add_dependencies(buildtests_cxx client_channel_stress_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@ -10024,6 +10025,45 @@ target_link_libraries(channel_filter_test
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(chttp2_settings_timeout_test
test/core/transport/chttp2/settings_timeout_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(chttp2_settings_timeout_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
PRIVATE third_party/googletest/googletest/include
PRIVATE third_party/googletest/googletest
PRIVATE third_party/googletest/googlemock/include
PRIVATE third_party/googletest/googlemock
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(chttp2_settings_timeout_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr_test_util
gpr
${_gRPC_GFLAGS_LIBRARIES}
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(cli_call_test
test/cpp/util/cli_call_test.cc
third_party/googletest/googletest/src/gtest-all.cc

@ -1113,6 +1113,7 @@ bm_metadata: $(BINDIR)/$(CONFIG)/bm_metadata
bm_pollset: $(BINDIR)/$(CONFIG)/bm_pollset
channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test
channel_filter_test: $(BINDIR)/$(CONFIG)/channel_filter_test
chttp2_settings_timeout_test: $(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test
cli_call_test: $(BINDIR)/$(CONFIG)/cli_call_test
client_channel_stress_test: $(BINDIR)/$(CONFIG)/client_channel_stress_test
client_crash_test: $(BINDIR)/$(CONFIG)/client_crash_test
@ -1555,6 +1556,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/bm_pollset \
$(BINDIR)/$(CONFIG)/channel_arguments_test \
$(BINDIR)/$(CONFIG)/channel_filter_test \
$(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test \
$(BINDIR)/$(CONFIG)/cli_call_test \
$(BINDIR)/$(CONFIG)/client_channel_stress_test \
$(BINDIR)/$(CONFIG)/client_crash_test \
@ -1681,6 +1683,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/bm_pollset \
$(BINDIR)/$(CONFIG)/channel_arguments_test \
$(BINDIR)/$(CONFIG)/channel_filter_test \
$(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test \
$(BINDIR)/$(CONFIG)/cli_call_test \
$(BINDIR)/$(CONFIG)/client_channel_stress_test \
$(BINDIR)/$(CONFIG)/client_crash_test \
@ -2065,6 +2068,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/channel_arguments_test || ( echo test channel_arguments_test failed ; exit 1 )
$(E) "[RUN] Testing channel_filter_test"
$(Q) $(BINDIR)/$(CONFIG)/channel_filter_test || ( echo test channel_filter_test failed ; exit 1 )
$(E) "[RUN] Testing chttp2_settings_timeout_test"
$(Q) $(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test || ( echo test chttp2_settings_timeout_test failed ; exit 1 )
$(E) "[RUN] Testing cli_call_test"
$(Q) $(BINDIR)/$(CONFIG)/cli_call_test || ( echo test cli_call_test failed ; exit 1 )
$(E) "[RUN] Testing client_channel_stress_test"
@ -14326,6 +14331,49 @@ endif
endif
CHTTP2_SETTINGS_TIMEOUT_TEST_SRC = \
test/core/transport/chttp2/settings_timeout_test.cc \
CHTTP2_SETTINGS_TIMEOUT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SETTINGS_TIMEOUT_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
$(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test: $(PROTOBUF_DEP) $(CHTTP2_SETTINGS_TIMEOUT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(CHTTP2_SETTINGS_TIMEOUT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/settings_timeout_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_chttp2_settings_timeout_test: $(CHTTP2_SETTINGS_TIMEOUT_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(CHTTP2_SETTINGS_TIMEOUT_TEST_OBJS:.o=.dep)
endif
endif
CLI_CALL_TEST_SRC = \
test/cpp/util/cli_call_test.cc \

@ -3815,6 +3815,18 @@ targets:
- grpc
- gpr
uses_polling: false
- name: chttp2_settings_timeout_test
gtest: true
build: test
language: c++
src:
- test/core/transport/chttp2/settings_timeout_test.cc
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
uses_polling: true
- name: cli_call_test
gtest: true
build: test

@ -114,6 +114,18 @@ grpc_cc_test(
],
)
grpc_cc_test(
name = "settings_timeout_test",
srcs = ["settings_timeout_test.cc"],
language = "C++",
deps = [
"//:gpr",
"//:grpc",
"//test/core/util:gpr_test_util",
"//test/core/util:grpc_test_util",
],
)
grpc_cc_test(
name = "varint_test",
srcs = ["varint_test.cc"],

@ -0,0 +1,258 @@
/*
*
* 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 <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <memory>
#include <thread>
#include "gtest/gtest.h"
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/pollset.h"
#include "src/core/lib/iomgr/pollset_set.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/tcp_client.h"
#include "src/core/lib/slice/slice_internal.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
namespace grpc_core {
namespace test {
namespace {
// A gRPC server, running in its own thread.
class ServerThread {
public:
explicit ServerThread(const char* address) : address_(address) {}
void Start() {
// Start server with 1-second handshake timeout.
grpc_arg arg;
arg.type = GRPC_ARG_INTEGER;
arg.key = const_cast<char*>(GRPC_ARG_SERVER_HANDSHAKE_TIMEOUT_MS);
arg.value.integer = 1000;
grpc_channel_args args = {1, &arg};
server_ = grpc_server_create(&args, nullptr);
ASSERT_TRUE(grpc_server_add_insecure_http2_port(server_, address_));
cq_ = grpc_completion_queue_create_for_next(nullptr);
grpc_server_register_completion_queue(server_, cq_, nullptr);
grpc_server_start(server_);
thread_.reset(new std::thread(std::bind(&ServerThread::Serve, this)));
}
void Shutdown() {
grpc_completion_queue* shutdown_cq =
grpc_completion_queue_create_for_pluck(nullptr);
grpc_server_shutdown_and_notify(server_, shutdown_cq, nullptr);
GPR_ASSERT(grpc_completion_queue_pluck(shutdown_cq, nullptr,
grpc_timeout_seconds_to_deadline(1),
nullptr).type == GRPC_OP_COMPLETE);
grpc_completion_queue_destroy(shutdown_cq);
grpc_server_destroy(server_);
grpc_completion_queue_destroy(cq_);
thread_->join();
}
private:
void Serve() {
// The completion queue should not return anything other than shutdown.
grpc_event ev = grpc_completion_queue_next(
cq_, gpr_inf_future(GPR_CLOCK_MONOTONIC), nullptr);
ASSERT_EQ(GRPC_QUEUE_SHUTDOWN, ev.type);
}
const char* address_; // Do not own.
grpc_server* server_ = nullptr;
grpc_completion_queue* cq_ = nullptr;
std::unique_ptr<std::thread> thread_;
};
// A TCP client that connects to the server, reads data until the server
// closes, and then terminates.
class Client {
public:
explicit Client(const char* server_address)
: server_address_(server_address) {}
void Connect() {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_resolved_addresses* server_addresses = nullptr;
grpc_error* error = grpc_blocking_resolve_address(server_address_,
"80", &server_addresses);
ASSERT_EQ(GRPC_ERROR_NONE, error) << grpc_error_string(error);
ASSERT_GE(server_addresses->naddrs, 1UL);
pollset_ = (grpc_pollset*)gpr_zalloc(grpc_pollset_size());
grpc_pollset_init(pollset_, &mu_);
grpc_pollset_set* pollset_set = grpc_pollset_set_create();
grpc_pollset_set_add_pollset(&exec_ctx, pollset_set, pollset_);
EventState state;
grpc_tcp_client_connect(&exec_ctx, state.closure(), &endpoint_,
pollset_set, nullptr /* channel_args */,
server_addresses->addrs, 1000);
ASSERT_TRUE(PollUntilDone(&exec_ctx, &state,
grpc_timespec_to_millis_round_up(
gpr_inf_future(GPR_CLOCK_MONOTONIC))));
ASSERT_EQ(GRPC_ERROR_NONE, state.error());
grpc_pollset_set_destroy(&exec_ctx, pollset_set);
grpc_endpoint_add_to_pollset(&exec_ctx, endpoint_, pollset_);
grpc_resolved_addresses_destroy(server_addresses);
grpc_exec_ctx_finish(&exec_ctx);
}
// Reads until an error is returned.
// Returns false if no error is returned by the deadline.
bool Read() {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_slice_buffer read_buffer;
grpc_slice_buffer_init(&read_buffer);
bool retval = true;
// Use a deadline of 3 seconds, which is a lot more than we should
// need for a 1-second timeout, but this helps avoid flakes.
grpc_millis deadline = grpc_exec_ctx_now(&exec_ctx) + 3000;
while (true) {
EventState state;
grpc_endpoint_read(&exec_ctx, endpoint_, &read_buffer, state.closure());
if (!PollUntilDone(&exec_ctx, &state, deadline)) {
retval = false;
break;
}
if (state.error() != GRPC_ERROR_NONE) break;
gpr_log(GPR_INFO, "client read %" PRIuPTR " bytes", read_buffer.length);
grpc_slice_buffer_reset_and_unref_internal(&exec_ctx, &read_buffer);
}
grpc_endpoint_shutdown(&exec_ctx, endpoint_,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("shutdown"));
grpc_slice_buffer_destroy_internal(&exec_ctx, &read_buffer);
grpc_exec_ctx_finish(&exec_ctx);
return retval;
}
void Shutdown() {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_endpoint_destroy(&exec_ctx, endpoint_);
grpc_pollset_shutdown(&exec_ctx, pollset_,
GRPC_CLOSURE_CREATE(&Client::PollsetDestroy, pollset_,
grpc_schedule_on_exec_ctx));
grpc_exec_ctx_finish(&exec_ctx);
}
private:
// State used to wait for an I/O event.
class EventState {
public:
EventState() {
GRPC_CLOSURE_INIT(&closure_, &EventState::OnEventDone, this,
grpc_schedule_on_exec_ctx);
}
~EventState() { GRPC_ERROR_UNREF(error_); }
grpc_closure* closure() { return &closure_; }
bool done() const { return done_; }
// Caller does NOT take ownership of the error.
grpc_error* error() const { return error_; }
private:
static void OnEventDone(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) {
gpr_log(GPR_INFO, "OnEventDone(): %s", grpc_error_string(error));
EventState* state = (EventState*)arg;
state->error_ = GRPC_ERROR_REF(error);
state->done_ = true;
}
grpc_closure closure_;
bool done_ = false;
grpc_error* error_ = GRPC_ERROR_NONE;
};
// Returns true if done, or false if deadline exceeded.
bool PollUntilDone(grpc_exec_ctx* exec_ctx, EventState* state,
grpc_millis deadline) {
while (true) {
grpc_pollset_worker* worker = nullptr;
gpr_mu_lock(mu_);
GRPC_LOG_IF_ERROR(
"grpc_pollset_work",
grpc_pollset_work(exec_ctx, pollset_, &worker,
grpc_exec_ctx_now(exec_ctx) + 1000));
gpr_mu_unlock(mu_);
if (state != nullptr && state->done()) return true;
if (grpc_exec_ctx_now(exec_ctx) >= deadline) return false;
}
}
static void PollsetDestroy(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) {
grpc_pollset* pollset = (grpc_pollset*)arg;
grpc_pollset_destroy(exec_ctx, pollset);
gpr_free(pollset);
}
const char* server_address_; // Do not own.
grpc_endpoint* endpoint_;
gpr_mu* mu_;
grpc_pollset* pollset_;
};
TEST(SettingsTimeout, Basic) {
// Construct server address string.
const int server_port = grpc_pick_unused_port_or_die();
char* server_address_string;
gpr_asprintf(&server_address_string, "localhost:%d", server_port);
// Start server.
gpr_log(GPR_INFO, "starting server on %s", server_address_string);
ServerThread server_thread(server_address_string);
server_thread.Start();
// Create client and connect to server.
gpr_log(GPR_INFO, "starting client connect");
Client client(server_address_string);
client.Connect();
// Client read. Should fail due to server dropping connection.
gpr_log(GPR_INFO, "starting client read");
EXPECT_TRUE(client.Read());
// Shut down client.
gpr_log(GPR_INFO, "shutting down client");
client.Shutdown();
// Shut down server.
gpr_log(GPR_INFO, "shutting down server");
server_thread.Shutdown();
// Clean up.
gpr_free(server_address_string);
}
} // namespace
} // namespace test
} // namespace grpc_core
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
grpc_test_init(argc, argv);
grpc_init();
int result = RUN_ALL_TESTS();
grpc_shutdown();
return result;
}

@ -2891,6 +2891,23 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc_test_util"
],
"headers": [],
"is_filegroup": false,
"language": "c++",
"name": "chttp2_settings_timeout_test",
"src": [
"test/core/transport/chttp2/settings_timeout_test.cc"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",

@ -3361,6 +3361,30 @@
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "chttp2_settings_timeout_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,

Loading…
Cancel
Save