[Import] Revert #34027 and #34129 (#34133)

This reverts commit 16b67ae312.
This commit is contained in:
Eugene Ostroukhov 2023-08-22 15:55:59 -07:00 committed by GitHub
parent 9413a34f1b
commit 440eef2288
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 227 additions and 695 deletions

80
CMakeLists.txt generated
View File

@ -1167,7 +1167,6 @@ if(gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx posix_event_engine_test)
endif()
add_dependencies(buildtests_cxx pre_stop_hook_server_test)
add_dependencies(buildtests_cxx prioritized_race_test)
add_dependencies(buildtests_cxx promise_endpoint_test)
add_dependencies(buildtests_cxx promise_factory_test)
@ -17785,83 +17784,6 @@ endif()
endif()
if(gRPC_BUILD_TESTS)
add_executable(pre_stop_hook_server_test
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/istio_echo.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/istio_echo.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/istio_echo.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/istio_echo.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.h
src/cpp/server/admin/admin_services.cc
src/cpp/server/csds/csds.cc
test/cpp/end2end/test_health_check_service_impl.cc
test/cpp/interop/pre_stop_hook_server.cc
test/cpp/interop/pre_stop_hook_server_test.cc
test/cpp/interop/xds_interop_server_lib.cc
)
target_compile_features(pre_stop_hook_server_test PUBLIC cxx_std_14)
target_include_directories(pre_stop_hook_server_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(pre_stop_hook_server_test
${_gRPC_ALLTARGETS_LIBRARIES}
gtest
grpc++_reflection
grpcpp_channelz
grpc_test_util
grpc++_test_config
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(prioritized_race_test
test/core/promise/prioritized_race_test.cc
)
@ -27588,7 +27510,6 @@ add_executable(xds_interop_server
src/cpp/server/admin/admin_services.cc
src/cpp/server/csds/csds.cc
test/cpp/end2end/test_health_check_service_impl.cc
test/cpp/interop/pre_stop_hook_server.cc
test/cpp/interop/xds_interop_server.cc
test/cpp/interop/xds_interop_server_lib.cc
)
@ -27660,7 +27581,6 @@ add_executable(xds_interop_server_test
src/cpp/server/admin/admin_services.cc
src/cpp/server/csds/csds.cc
test/cpp/end2end/test_health_check_service_impl.cc
test/cpp/interop/pre_stop_hook_server.cc
test/cpp/interop/xds_interop_server_lib.cc
test/cpp/interop/xds_interop_server_test.cc
)

View File

@ -12223,37 +12223,6 @@ targets:
platforms:
- linux
- posix
- name: pre_stop_hook_server_test
gtest: true
build: test
language: c++
headers:
- src/cpp/server/csds/csds.h
- test/cpp/end2end/test_health_check_service_impl.h
- test/cpp/interop/pre_stop_hook_server.h
- test/cpp/interop/xds_interop_server_lib.h
src:
- src/proto/grpc/health/v1/health.proto
- src/proto/grpc/testing/empty.proto
- src/proto/grpc/testing/istio_echo.proto
- src/proto/grpc/testing/messages.proto
- src/proto/grpc/testing/test.proto
- src/proto/grpc/testing/xds/v3/base.proto
- src/proto/grpc/testing/xds/v3/config_dump.proto
- src/proto/grpc/testing/xds/v3/csds.proto
- src/proto/grpc/testing/xds/v3/percent.proto
- src/cpp/server/admin/admin_services.cc
- src/cpp/server/csds/csds.cc
- test/cpp/end2end/test_health_check_service_impl.cc
- test/cpp/interop/pre_stop_hook_server.cc
- test/cpp/interop/pre_stop_hook_server_test.cc
- test/cpp/interop/xds_interop_server_lib.cc
deps:
- gtest
- grpc++_reflection
- grpcpp_channelz
- grpc_test_util
- grpc++_test_config
- name: prioritized_race_test
gtest: true
build: test
@ -17584,7 +17553,6 @@ targets:
headers:
- src/cpp/server/csds/csds.h
- test/cpp/end2end/test_health_check_service_impl.h
- test/cpp/interop/pre_stop_hook_server.h
- test/cpp/interop/xds_interop_server_lib.h
src:
- src/proto/grpc/health/v1/health.proto
@ -17598,7 +17566,6 @@ targets:
- src/cpp/server/admin/admin_services.cc
- src/cpp/server/csds/csds.cc
- test/cpp/end2end/test_health_check_service_impl.cc
- test/cpp/interop/pre_stop_hook_server.cc
- test/cpp/interop/xds_interop_server.cc
- test/cpp/interop/xds_interop_server_lib.cc
deps:
@ -17613,7 +17580,6 @@ targets:
headers:
- src/cpp/server/csds/csds.h
- test/cpp/end2end/test_health_check_service_impl.h
- test/cpp/interop/pre_stop_hook_server.h
- test/cpp/interop/xds_interop_server_lib.h
src:
- src/proto/grpc/health/v1/health.proto
@ -17628,7 +17594,6 @@ targets:
- src/cpp/server/admin/admin_services.cc
- src/cpp/server/csds/csds.cc
- test/cpp/end2end/test_health_check_service_impl.cc
- test/cpp/interop/pre_stop_hook_server.cc
- test/cpp/interop/xds_interop_server_lib.cc
- test/cpp/interop/xds_interop_server_test.cc
deps:

View File

@ -219,7 +219,7 @@ message LoadBalancerStatsResponse {
message RpcMetadata {
// metadata values for each rpc for the keys specified in
// LoadBalancerStatsRequest.metadata_keys.
// metadata keys and values are returned exactly as was received
// metadata keys and values are returned exactly as was recieved
// from the server.
repeated MetadataEntry metadata = 1;
}
@ -309,23 +309,3 @@ message TestOrcaReport {
map<string, double> request_cost = 3;
map<string, double> utilization = 4;
}
enum HookRequestCommand {
// Start the HTTP endpoint
START = 0;
// Stop
STOP = 1;
// Return from HTTP GET/POST
RETURN = 2;
}
message HookRequest {
HookRequestCommand command = 1;
int32 grpc_code_to_return = 2;
string grpc_status_description = 3;
// Server port to listen to
int32 server_port = 4;
}
message HookResponse {
}

View File

@ -23,8 +23,6 @@ import "src/proto/grpc/testing/messages.proto";
package grpc.testing;
option java_package = "io.grpc.testing.integration";
// A simple service to test the various types of RPCs and experiment with
// performance with various types of payload.
service TestService {
@ -91,17 +89,10 @@ service LoadBalancerStatsService {
returns (LoadBalancerAccumulatedStatsResponse) {}
}
// Hook service that may be started on request by calling XdsUpdateHealthService
// with HookRequestCommand::START
service HookService {
rpc Hook(grpc.testing.Empty) returns (grpc.testing.Empty);
}
// A service to remotely control health status of an xDS test server.
service XdsUpdateHealthService {
rpc SetServing(grpc.testing.Empty) returns (grpc.testing.Empty);
rpc SetNotServing(grpc.testing.Empty) returns (grpc.testing.Empty);
rpc SendHookRequest(HookRequest) returns (HookResponse);
}
// A service to dynamically update the configuration of an xDS test client.

View File

@ -47,7 +47,7 @@ def test_runner_log(msg):
sys.stderr.write('\n%s: %s\n' % (__file__, msg))
def python_args(arg_list):
if platform.system() == 'Windows':
if platform.system() == 'Windows' and arg_list[0].endswith('.py'):
return [sys.executable] + arg_list
return arg_list

View File

@ -287,13 +287,9 @@ grpc_cc_library(
name = "xds_interop_server_lib",
testonly = True,
srcs = [
"pre_stop_hook_server.cc",
"xds_interop_server_lib.cc",
],
hdrs = [
"pre_stop_hook_server.h",
"xds_interop_server_lib.h",
],
hdrs = ["xds_interop_server_lib.h"],
deps = [
"//:grpc++",
"//:grpc++_reflection",
@ -323,21 +319,6 @@ grpc_cc_binary(
],
)
grpc_cc_test(
name = "pre_stop_hook_server_test",
srcs = [
"pre_stop_hook_server_test.cc",
],
external_deps = ["gtest"],
deps = [
":xds_interop_server_lib",
"//:grpc++",
"//src/proto/grpc/testing:istio_echo_proto",
"//test/core/util:grpc_test_util",
"//test/cpp/util:test_config",
],
)
grpc_cc_test(
name = "xds_interop_server_test",
srcs = [

View File

@ -1,198 +0,0 @@
//
//
// Copyright 2023 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/cpp/interop/pre_stop_hook_server.h"
#include <thread>
#include "absl/strings/str_format.h"
#include <grpcpp/grpcpp.h>
#include "src/proto/grpc/testing/test.grpc.pb.h"
namespace grpc {
namespace testing {
namespace {
class HookServiceImpl final : public HookService::CallbackService {
public:
ServerUnaryReactor* Hook(CallbackServerContext* context,
const Empty* /* request */,
Empty* /* reply */) override {
grpc_core::MutexLock lock(&mu_);
auto reactor = context->DefaultReactor();
if (pending_status_) {
reactor->Finish(std::move(*pending_status_));
pending_status_ = absl::nullopt;
} else if (done_) {
reactor->Finish(Status(StatusCode::ABORTED, "Shutting down"));
} else {
pending_requests_.push_back(reactor);
}
request_var_.SignalAll();
return reactor;
}
void SetReturnStatus(const Status& status) {
grpc_core::MutexLock lock(&mu_);
if (pending_requests_.empty()) {
pending_status_ = status;
} else {
auto reactor = pending_requests_.begin();
(*reactor)->Finish(status);
pending_requests_.erase(reactor);
}
request_var_.SignalAll();
}
bool TestOnlyExpectRequests(size_t expected_requests_count,
const absl::Duration& timeout) {
grpc_core::MutexLock lock(&mu_);
auto deadline = absl::Now() + timeout;
while (pending_requests_.size() < expected_requests_count &&
!request_var_.WaitWithDeadline(&mu_, deadline)) {
}
return pending_requests_.size() >= expected_requests_count;
}
void Stop() {
grpc_core::MutexLock lock(&mu_);
for (auto request : pending_requests_) {
request->Finish(Status(StatusCode::ABORTED, "Shutting down"));
}
pending_requests_.clear();
}
private:
grpc_core::Mutex mu_;
grpc_core::CondVar request_var_ ABSL_GUARDED_BY(&mu_);
absl::optional<Status> pending_status_ ABSL_GUARDED_BY(&mu_);
std::vector<ServerUnaryReactor*> pending_requests_ ABSL_GUARDED_BY(&mu_);
bool done_ ABSL_GUARDED_BY(&mu_) = false;
};
enum class State { kNew, kWaiting, kDone, kShuttingDown };
std::unique_ptr<Server> BuildHookServer(HookServiceImpl* service, int port) {
ServerBuilder builder;
builder.AddListeningPort(absl::StrFormat("0.0.0.0:%d", port),
grpc::InsecureServerCredentials());
builder.RegisterService(service);
return builder.BuildAndStart();
}
} // namespace
class PreStopHookServer {
public:
explicit PreStopHookServer(int port, const absl::Duration& startup_timeout)
: server_(BuildHookServer(&hook_service_, port)),
server_thread_(PreStopHookServer::ServerThread, this) {
WaitForState(State::kWaiting, startup_timeout);
}
~PreStopHookServer() {
hook_service_.Stop();
SetState(State::kShuttingDown);
server_->Shutdown();
server_thread_.join();
}
State GetState() {
grpc_core::MutexLock lock(&mu_);
return state_;
}
void SetState(State state) {
grpc_core::MutexLock lock(&mu_);
state_ = state;
condition_.SignalAll();
}
void SetReturnStatus(const Status& status) {
hook_service_.SetReturnStatus(status);
}
bool TestOnlyExpectRequests(size_t expected_requests_count,
absl::Duration timeout) {
return hook_service_.TestOnlyExpectRequests(expected_requests_count,
timeout);
}
private:
bool WaitForState(State state, const absl::Duration& timeout) {
grpc_core::MutexLock lock(&mu_);
auto deadline = absl::Now() + timeout;
while (state_ != state && !condition_.WaitWithDeadline(&mu_, deadline)) {
}
return state_ == state;
}
static void ServerThread(PreStopHookServer* server) {
server->SetState(State::kWaiting);
server->server_->Wait();
server->SetState(State::kDone);
}
HookServiceImpl hook_service_;
grpc_core::Mutex mu_;
grpc_core::CondVar condition_ ABSL_GUARDED_BY(mu_);
State state_ ABSL_GUARDED_BY(mu_) = State::kNew;
std::unique_ptr<Server> server_;
std::thread server_thread_;
};
Status PreStopHookServerManager::Start(int port, size_t timeout_s) {
if (server_) {
return Status(StatusCode::ALREADY_EXISTS,
"Pre hook server is already running");
}
server_ = std::unique_ptr<PreStopHookServer, PreStopHookServerDeleter>(
new PreStopHookServer(port, absl::Seconds(timeout_s)),
PreStopHookServerDeleter());
return server_->GetState() == State::kWaiting
? Status::OK
: Status(StatusCode::DEADLINE_EXCEEDED, "Server have not started");
}
Status PreStopHookServerManager::Stop() {
if (!server_) {
return Status(StatusCode::UNAVAILABLE, "Pre hook server is not running");
}
server_.reset();
return Status::OK;
}
void PreStopHookServerManager::Return(StatusCode code,
absl::string_view description) {
server_->SetReturnStatus(Status(code, std::string(description)));
}
bool PreStopHookServerManager::TestOnlyExpectRequests(
size_t expected_requests_count, const absl::Duration& timeout) {
return server_->TestOnlyExpectRequests(expected_requests_count, timeout);
}
void PreStopHookServerManager::PreStopHookServerDeleter::operator()(
PreStopHookServer* server) {
delete server;
}
} // namespace testing
} // namespace grpc

View File

@ -1,62 +0,0 @@
//
//
// Copyright 2023 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.
//
//
#ifndef GRPC_TEST_CPP_INTEROP_PRE_STOP_HOOK_SERVER_H
#define GRPC_TEST_CPP_INTEROP_PRE_STOP_HOOK_SERVER_H
#include <grpc/support/port_platform.h>
#include <thread>
#include <grpcpp/server.h>
#include "src/core/lib/config/core_configuration.h"
namespace grpc {
namespace testing {
// Implementation of the pre-stop hook server. An instance is created to start
// a server and destroyed to stop one.
class PreStopHookServer;
// Interface for interacting with PreStopHookServer. Provides operations
// required by the protocol, such as start, stop and return from the call.
class PreStopHookServerManager {
public:
Status Start(int port, size_t timeout_s);
Status Stop();
void Return(StatusCode code, absl::string_view description);
// Suspends the thread until there are pending requests. Returns false
// if the necessary number of requests have not been received before the
// timeout.
bool TestOnlyExpectRequests(
size_t expected_requests_count,
const absl::Duration& timeout = absl::Seconds(15));
private:
// Custom deleter so we don't have to include PreStopHookServer in this header
struct PreStopHookServerDeleter {
void operator()(PreStopHookServer* server);
};
std::unique_ptr<PreStopHookServer, PreStopHookServerDeleter> server_;
};
} // namespace testing
} // namespace grpc
#endif // GRPC_TEST_CPP_INTEROP_PRE_STOP_HOOK_SERVER_H

View File

@ -1,176 +0,0 @@
//
// Copyright 2023 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/cpp/interop/pre_stop_hook_server.h"
#include <map>
#include <memory>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "absl/strings/str_format.h"
#include <grpc/grpc.h>
#include <grpcpp/grpcpp.h>
#include "src/proto/grpc/testing/test.grpc.pb.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
namespace grpc {
namespace testing {
namespace {
struct CallInfo {
public:
ClientContext context;
Empty request;
Empty response;
absl::optional<Status> WaitForStatus(
absl::Duration timeout = absl::Seconds(1)) {
grpc_core::MutexLock lock(&mu);
if (!status_.has_value()) {
cv.WaitWithTimeout(&mu, timeout);
}
return status_;
}
void SetStatus(const Status& status) {
grpc_core::MutexLock lock(&mu);
status_ = status;
cv.SignalAll();
}
private:
grpc_core::Mutex mu;
grpc_core::CondVar cv;
absl::optional<Status> status_;
};
TEST(PreStopHookServer, StartDoRequestStop) {
int port = grpc_pick_unused_port_or_die();
PreStopHookServerManager server;
Status start_status = server.Start(port, 15);
ASSERT_TRUE(start_status.ok()) << start_status.error_message();
auto channel = CreateChannel(absl::StrFormat("127.0.0.1:%d", port),
InsecureChannelCredentials());
ASSERT_TRUE(channel);
CallInfo info;
HookService::Stub stub(std::move(channel));
stub.async()->Hook(&info.context, &info.request, &info.response,
[&info](Status status) { info.SetStatus(status); });
ASSERT_EQ(server.TestOnlyExpectRequests(1), 1);
server.Return(StatusCode::INTERNAL, "Just a test");
auto status = info.WaitForStatus();
ASSERT_TRUE(status.has_value());
EXPECT_EQ(status->error_code(), StatusCode::INTERNAL);
EXPECT_EQ(status->error_message(), "Just a test");
}
TEST(PreStopHookServer, StartServerWhileAlreadyRunning) {
int port = grpc_pick_unused_port_or_die();
PreStopHookServerManager server;
Status status = server.Start(port, 15);
ASSERT_TRUE(status.ok()) << status.error_message();
status = server.Start(port, 15);
ASSERT_EQ(status.error_code(), StatusCode::ALREADY_EXISTS)
<< status.error_message();
}
TEST(PreStopHookServer, StopServerWhileRequestPending) {
int port = grpc_pick_unused_port_or_die();
PreStopHookServerManager server;
Status start_status = server.Start(port, 15);
ASSERT_TRUE(start_status.ok()) << start_status.error_message();
auto channel = CreateChannel(absl::StrFormat("127.0.0.1:%d", port),
InsecureChannelCredentials());
ASSERT_TRUE(channel);
CallInfo info;
HookService::Stub stub(std::move(channel));
stub.async()->Hook(&info.context, &info.request, &info.response,
[&info](Status status) { info.SetStatus(status); });
ASSERT_EQ(server.TestOnlyExpectRequests(1), 1);
ASSERT_TRUE(server.Stop().ok());
auto status = info.WaitForStatus();
ASSERT_TRUE(status.has_value());
EXPECT_EQ(status->error_code(), StatusCode::ABORTED);
}
TEST(PreStopHookServer, RespondToMultiplePendingRequests) {
std::array<CallInfo, 2> info;
int port = grpc_pick_unused_port_or_die();
PreStopHookServerManager server;
Status start_status = server.Start(port, 15);
ASSERT_TRUE(start_status.ok()) << start_status.error_message();
auto channel = CreateChannel(absl::StrFormat("127.0.0.1:%d", port),
InsecureChannelCredentials());
ASSERT_TRUE(channel);
HookService::Stub stub(std::move(channel));
stub.async()->Hook(&info[0].context, &info[0].request, &info[0].response,
[&info](Status status) { info[0].SetStatus(status); });
ASSERT_EQ(server.TestOnlyExpectRequests(1), 1);
stub.async()->Hook(&info[1].context, &info[1].request, &info[1].response,
[&info](Status status) { info[1].SetStatus(status); });
server.TestOnlyExpectRequests(2);
server.Return(StatusCode::INTERNAL, "Just a test");
auto status = info[0].WaitForStatus();
ASSERT_TRUE(status.has_value());
EXPECT_EQ(status->error_code(), StatusCode::INTERNAL);
EXPECT_EQ(status->error_message(), "Just a test");
status = info[1].WaitForStatus();
EXPECT_FALSE(status.has_value());
}
TEST(PreStopHookServer, StopServerThatNotStarted) {
PreStopHookServerManager server;
Status status = server.Stop();
EXPECT_EQ(status.error_code(), StatusCode::UNAVAILABLE)
<< status.error_message();
}
TEST(PreStopHookServer, SetStatusBeforeRequestReceived) {
int port = grpc_pick_unused_port_or_die();
PreStopHookServerManager server;
Status start_status = server.Start(port, 15);
server.Return(StatusCode::INTERNAL, "Just a test");
ASSERT_TRUE(start_status.ok()) << start_status.error_message();
auto channel = CreateChannel(absl::StrFormat("127.0.0.1:%d", port),
InsecureChannelCredentials());
ASSERT_TRUE(channel);
HookService::Stub stub(std::move(channel));
CallInfo info;
stub.async()->Hook(&info.context, &info.request, &info.response,
[&info](Status status) { info.SetStatus(status); });
auto status = info.WaitForStatus();
ASSERT_TRUE(status.has_value());
EXPECT_EQ(status->error_code(), StatusCode::INTERNAL);
EXPECT_EQ(status->error_message(), "Just a test");
}
} // namespace
} // namespace testing
} // namespace grpc
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
grpc::testing::TestEnvironment env(&argc, argv);
grpc_init();
auto result = RUN_ALL_TESTS();
grpc_shutdown();
return result;
}

View File

@ -41,7 +41,6 @@
#include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h"
#include "test/cpp/end2end/test_health_check_service_impl.h"
#include "test/cpp/interop/pre_stop_hook_server.h"
namespace grpc {
namespace testing {
@ -114,10 +113,8 @@ class TestServiceImpl : public TestService::Service {
class XdsUpdateHealthServiceImpl : public XdsUpdateHealthService::Service {
public:
explicit XdsUpdateHealthServiceImpl(
HealthCheckServiceImpl* health_check_service,
std::unique_ptr<PreStopHookServerManager> pre_stop_hook_server)
: health_check_service_(health_check_service),
pre_stop_hook_server_(std::move(pre_stop_hook_server)) {}
HealthCheckServiceImpl* health_check_service)
: health_check_service_(health_check_service) {}
Status SetServing(ServerContext* /* context */, const Empty* /* request */,
Empty* /* response */) override {
@ -133,29 +130,8 @@ class XdsUpdateHealthServiceImpl : public XdsUpdateHealthService::Service {
return Status::OK;
}
Status SendHookRequest(ServerContext* /* context */,
const HookRequest* request,
HookResponse* /* response */) override {
switch (request->command()) {
case HookRequestCommand::START:
return pre_stop_hook_server_->Start(request->server_port(), 30 /* s */);
case HookRequestCommand::STOP:
return pre_stop_hook_server_->Stop();
case HookRequestCommand::RETURN:
pre_stop_hook_server_->Return(
static_cast<StatusCode>(request->grpc_code_to_return()),
request->grpc_status_description());
return Status::OK;
default:
return Status(
StatusCode::INVALID_ARGUMENT,
absl::StrFormat("Invalid command %d", request->command()));
}
}
private:
HealthCheckServiceImpl* const health_check_service_;
std::unique_ptr<PreStopHookServerManager> pre_stop_hook_server_;
};
} // namespace
@ -213,8 +189,7 @@ void RunServer(bool secure_mode, const int port, const int maintenance_port,
health_check_service.SetStatus(
"grpc.testing.XdsUpdateHealthService",
grpc::health::v1::HealthCheckResponse::SERVING);
XdsUpdateHealthServiceImpl update_health_service(
&health_check_service, std::make_unique<PreStopHookServerManager>());
XdsUpdateHealthServiceImpl update_health_service(&health_check_service);
grpc::reflection::InitProtoReflectionServerBuilderPlugin();
ServerBuilder builder;

View File

@ -54,4 +54,9 @@ grpc_cc_test(
],
)
filegroup(
name = "resolver_test_record_groups",
srcs = ["resolver_test_record_groups.yaml"],
)
generate_resolver_component_tests()

View File

@ -75,6 +75,7 @@ def generate_resolver_component_tests():
],
external_deps = [
"absl/flags:flag",
"absl/strings",
],
deps = [
"//test/cpp/util:test_util%s" % unsecure_build_config_suffix,
@ -83,6 +84,7 @@ def generate_resolver_component_tests():
"//:grpc%s" % unsecure_build_config_suffix,
"//:gpr",
"//test/cpp/util:test_config",
"//test/cpp/util/windows:manifest_file",
],
data = [
":resolver_component_tests_runner",
@ -90,7 +92,7 @@ def generate_resolver_component_tests():
"//test/cpp/naming/utils:dns_server",
"//test/cpp/naming/utils:dns_resolver",
"//test/cpp/naming/utils:tcp_connect",
"resolver_test_record_groups.yaml", # include the transitive dependency so that the dns server py binary can locate this
"//test/cpp/naming:resolver_test_record_groups", # include the transitive dependency so that the dns server py binary can locate this
],
args = [
"--test_bin_name=resolver_component_test%s" % unsecure_build_config_suffix,

View File

@ -47,7 +47,7 @@ def test_runner_log(msg):
sys.stderr.write('\n%s: %s\n' % (__file__, msg))
def python_args(arg_list):
if platform.system() == 'Windows':
if platform.system() == 'Windows' and arg_list[0].endswith('.py'):
return [sys.executable] + arg_list
return arg_list

View File

@ -1,6 +1,4 @@
//
//
// Copyright 2017 gRPC authors.
// Copyright 2017 The gRPC Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -13,13 +11,17 @@
// 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/support/port_platform.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#ifndef GPR_WINDOWS
#include <unistd.h>
#endif // GPR_WINDOWS
#include <memory>
#include <string>
#include <thread>
#include <vector>
@ -43,6 +45,9 @@
#include "test/core/util/test_config.h"
#include "test/cpp/util/subprocess.h"
#include "test/cpp/util/test_config.h"
#ifdef GPR_WINDOWS
#include "test/cpp/util/windows/manifest_file.h"
#endif // GPR_WINDOWS
ABSL_FLAG(
bool, running_under_bazel, false,
@ -68,48 +73,22 @@ namespace grpc {
namespace testing {
void InvokeResolverComponentTestsRunner(
int InvokeResolverComponentTestsRunner(
std::string test_runner_bin_path, const std::string& test_bin_path,
const std::string& dns_server_bin_path,
const std::string& records_config_path,
const std::string& dns_resolver_bin_path,
const std::string& tcp_connect_bin_path) {
int dns_server_port = grpc_pick_unused_port_or_die();
SubProcess* test_driver = new SubProcess(
auto test_driver = std::make_unique<SubProcess>(std::vector<std::string>(
{std::move(test_runner_bin_path), "--test_bin_path=" + test_bin_path,
"--dns_server_bin_path=" + dns_server_bin_path,
"--records_config_path=" + records_config_path,
"--dns_server_port=" + std::to_string(dns_server_port),
"--dns_resolver_bin_path=" + dns_resolver_bin_path,
"--tcp_connect_bin_path=" + tcp_connect_bin_path,
"--extra_args=" + absl::GetFlag(FLAGS_extra_args)});
gpr_mu test_driver_mu;
gpr_mu_init(&test_driver_mu);
gpr_cv test_driver_cv;
gpr_cv_init(&test_driver_cv);
int status = test_driver->Join();
if (WIFEXITED(status)) {
if (WEXITSTATUS(status)) {
grpc_core::Crash(absl::StrFormat(
"Resolver component test test-runner exited with code %d",
WEXITSTATUS(status)));
}
} else if (WIFSIGNALED(status)) {
grpc_core::Crash(absl::StrFormat(
"Resolver component test test-runner ended from signal %d",
WTERMSIG(status)));
} else {
grpc_core::Crash(absl::StrFormat(
"Resolver component test test-runner ended with unknown status %d",
status));
}
gpr_mu_lock(&test_driver_mu);
gpr_cv_signal(&test_driver_cv);
gpr_mu_unlock(&test_driver_mu);
delete test_driver;
gpr_mu_destroy(&test_driver_mu);
gpr_cv_destroy(&test_driver_cv);
"--extra_args=" + absl::GetFlag(FLAGS_extra_args)}));
return test_driver->Join();
}
} // namespace testing
@ -122,12 +101,14 @@ int main(int argc, char** argv) {
grpc_init();
GPR_ASSERT(!absl::GetFlag(FLAGS_test_bin_name).empty());
std::string my_bin = argv[0];
int result = 0;
if (absl::GetFlag(FLAGS_running_under_bazel)) {
GPR_ASSERT(!absl::GetFlag(FLAGS_grpc_test_directory_relative_to_test_srcdir)
.empty());
// Use bazel's TEST_SRCDIR environment variable to locate the "test data"
// binaries.
auto test_srcdir = grpc_core::GetEnv("TEST_SRCDIR");
#ifndef GPR_WINDOWS
std::string const bin_dir =
test_srcdir.value() +
absl::GetFlag(FLAGS_grpc_test_directory_relative_to_test_srcdir) +
@ -135,18 +116,43 @@ int main(int argc, char** argv) {
// Invoke bazel's executeable links to the .sh and .py scripts (don't use
// the .sh and .py suffixes) to make
// sure that we're using bazel's test environment.
grpc::testing::InvokeResolverComponentTestsRunner(
result = grpc::testing::InvokeResolverComponentTestsRunner(
bin_dir + "/resolver_component_tests_runner",
bin_dir + "/" + absl::GetFlag(FLAGS_test_bin_name),
bin_dir + "/utils/dns_server",
bin_dir + "/resolver_test_record_groups.yaml",
bin_dir + "/utils/dns_resolver", bin_dir + "/utils/tcp_connect");
#else
grpc::testing::ManifestFile manifest_file(
grpc::testing::NormalizeFilePath(test_srcdir.value()) + "\\MANIFEST");
grpc::testing::InvokeResolverComponentTestsRunner(
grpc::testing::NormalizeFilePath(
manifest_file.Get("com_github_grpc_grpc/test/cpp/naming/"
"resolver_component_tests_runner.exe")),
grpc::testing::NormalizeFilePath(
manifest_file.Get("com_github_grpc_grpc/test/cpp/naming/" +
absl::GetFlag(FLAGS_test_bin_name) + ".exe")),
grpc::testing::NormalizeFilePath(manifest_file.Get(
"com_github_grpc_grpc/test/cpp/naming/utils/dns_server.exe")),
grpc::testing::NormalizeFilePath(
manifest_file.Get("com_github_grpc_grpc/test/cpp/naming/"
"resolver_test_record_groups.yaml")),
grpc::testing::NormalizeFilePath(manifest_file.Get(
"com_github_grpc_grpc/test/cpp/naming/utils/dns_resolver.exe")),
grpc::testing::NormalizeFilePath(manifest_file.Get(
"com_github_grpc_grpc/test/cpp/naming/utils/tcp_connect.exe")));
#endif // GPR_WINDOWS
} else {
#ifdef GPR_WINDOWS
grpc_core::Crash(
"Resolver component tests runner invoker does not support running "
"without Bazel on Windows for now.");
#endif // GPR_WINDOWS
// Get the current binary's directory relative to repo root to invoke the
// correct build config (asan/tsan/dbg, etc.).
std::string const bin_dir = my_bin.substr(0, my_bin.rfind('/'));
// Invoke the .sh and .py scripts directly where they are in source code.
grpc::testing::InvokeResolverComponentTestsRunner(
result = grpc::testing::InvokeResolverComponentTestsRunner(
"test/cpp/naming/resolver_component_tests_runner.py",
bin_dir + "/" + absl::GetFlag(FLAGS_test_bin_name),
"test/cpp/naming/utils/dns_server.py",
@ -155,5 +161,5 @@ int main(int argc, char** argv) {
"test/cpp/naming/utils/tcp_connect.py");
}
grpc_shutdown();
return 0;
return result;
}

View File

@ -0,0 +1,39 @@
# Copyright 2023 The 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_package")
licenses(["notice"])
grpc_package(
name = "test/cpp/util/windows",
visibility = "tests",
)
grpc_cc_library(
name = "manifest_file",
testonly = True,
srcs = [
"manifest_file.cc",
],
hdrs = [
"manifest_file.h",
],
external_deps = [
"absl/strings",
],
deps = [
"//:gpr",
],
)

View File

@ -0,0 +1,71 @@
// Copyright 2023 The 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/support/port_platform.h>
#include "test/cpp/util/windows/manifest_file.h"
#ifdef GPR_WINDOWS
#include <fstream>
#include <string>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_replace.h"
#include "absl/strings/str_split.h"
#include <grpc/support/log.h>
#include "src/core/lib/gprpp/crash.h"
namespace grpc {
namespace testing {
std::string NormalizeFilePath(const std::string& filepath) {
return absl::StrReplaceAll(filepath, {{"/", "\\"}});
}
ManifestFile::ManifestFile(const std::string& filepath)
: filestream_(filepath, std::ios::in | std::ios::binary) {
if (!filestream_.is_open()) {
grpc_core::Crash(absl::StrFormat("Failed to open %s", filepath));
}
}
std::string ManifestFile::Get(const std::string& key) {
auto iter = cache_.find(key);
if (iter != cache_.end()) {
return iter->second;
}
do {
std::string line;
std::getline(filestream_, line);
if (!line.empty()) {
std::vector<std::string> kv = absl::StrSplit(line, " ");
GPR_ASSERT(kv.size() == 2);
cache_.emplace(kv[0], kv[1]);
if (kv[0] == key) {
return kv[1];
}
}
} while (!filestream_.eof() && !filestream_.fail());
grpc_core::Crash(
absl::StrFormat("Failed to find key: %s in MANIFEST file", key));
}
} // namespace testing
} // namespace grpc
#endif // GPR_WINDOWS

View File

@ -0,0 +1,57 @@
// Copyright 2023 The 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.
#ifndef GRPC_TEST_CPP_UTIL_WINDOWS_MANIFEST_FILE_H
#define GRPC_TEST_CPP_UTIL_WINDOWS_MANIFEST_FILE_H
#include <grpc/support/port_platform.h>
#ifdef GPR_WINDOWS
#include <fstream>
#include <string>
#include <unordered_map>
namespace grpc {
namespace testing {
std::string NormalizeFilePath(const std::string& filepath);
// This class is used for handling Runfiles for a Bazel target on Windows (e.g.
// the output of targets specified in the data attribute of the target). On
// Linux/macOS, Bazel creates a runfiles tree which contains symlinks to the
// actual runfiles. But on Windows, it only creates a MANIFEST file which
// contains a list of <symlink relative path, absolute symlink target path>.
// Thus one initializes a ManifestFile object with the filepath to a MANIFEST
// file and uses it as a key-value datastore by querying the absolute symlink
// target path with the imaginative symlink relative path. See
// https://github.com/bazelbuild/bazel/issues/4261#issuecomment-350723457 for
// more details.
class ManifestFile {
public:
explicit ManifestFile(const std::string& filepath);
std::string Get(const std::string& key);
private:
std::fstream filestream_;
std::unordered_map<std::string, std::string> cache_;
};
} // namespace testing
} // namespace grpc
#endif // GPR_WINDOWS
#endif // GRPC_TEST_CPP_UTIL_WINDOWS_MANIFEST_FILE_H

View File

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