|
|
|
@ -46,7 +46,7 @@ |
|
|
|
|
#include <grpc/support/json.h> |
|
|
|
|
#include <grpcpp/impl/codegen/config_protobuf.h> |
|
|
|
|
|
|
|
|
|
#include "src/core/lib/event_engine/default_event_engine.h" |
|
|
|
|
#include "src/core/lib/iomgr/timer_manager.h" |
|
|
|
|
#include "src/core/util/debug_location.h" |
|
|
|
|
#include "src/core/util/json/json.h" |
|
|
|
|
#include "src/core/util/json/json_args.h" |
|
|
|
@ -59,6 +59,8 @@ |
|
|
|
|
#include "src/core/xds/xds_client/xds_resource_type_impl.h" |
|
|
|
|
#include "src/proto/grpc/testing/xds/v3/base.pb.h" |
|
|
|
|
#include "src/proto/grpc/testing/xds/v3/discovery.pb.h" |
|
|
|
|
#include "test/core/event_engine/event_engine_test_utils.h" |
|
|
|
|
#include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h" |
|
|
|
|
#include "test/core/test_util/scoped_env_var.h" |
|
|
|
|
#include "test/core/test_util/test_config.h" |
|
|
|
|
#include "test/core/xds/xds_client_test_peer.h" |
|
|
|
@ -73,6 +75,7 @@ |
|
|
|
|
|
|
|
|
|
using envoy::service::discovery::v3::DiscoveryRequest; |
|
|
|
|
using envoy::service::discovery::v3::DiscoveryResponse; |
|
|
|
|
using grpc_event_engine::experimental::FuzzingEventEngine; |
|
|
|
|
|
|
|
|
|
namespace grpc_core { |
|
|
|
|
namespace testing { |
|
|
|
@ -252,6 +255,9 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
all_resources_required_in_sotw>, |
|
|
|
|
ResourceStruct>::WatcherInterface { |
|
|
|
|
public: |
|
|
|
|
explicit Watcher(std::shared_ptr<FuzzingEventEngine> event_engine) |
|
|
|
|
: event_engine_(std::move(event_engine)) {} |
|
|
|
|
|
|
|
|
|
~Watcher() override { |
|
|
|
|
MutexLock lock(&mu_); |
|
|
|
|
EXPECT_THAT(queue_, ::testing::IsEmpty()) |
|
|
|
@ -270,42 +276,46 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Returns true if no event is received during the timeout period.
|
|
|
|
|
bool ExpectNoEvent(absl::Duration timeout) { |
|
|
|
|
MutexLock lock(&mu_); |
|
|
|
|
return !WaitForEventLocked(timeout); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool HasEvent() { |
|
|
|
|
MutexLock lock(&mu_); |
|
|
|
|
return !queue_.empty(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Returns true if no event is received after draining the fuzzing
|
|
|
|
|
// EE queue.
|
|
|
|
|
bool ExpectNoEvent() { |
|
|
|
|
event_engine_->TickUntilIdle(); |
|
|
|
|
return !HasEvent(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
absl::optional<ResourceAndReadDelayHandle> WaitForNextResourceAndHandle( |
|
|
|
|
absl::Duration timeout = absl::Seconds(1), |
|
|
|
|
SourceLocation location = SourceLocation()) { |
|
|
|
|
MutexLock lock(&mu_); |
|
|
|
|
if (!WaitForEventLocked(timeout)) return absl::nullopt; |
|
|
|
|
Event& event = queue_.front(); |
|
|
|
|
if (!absl::holds_alternative<ResourceAndReadDelayHandle>(event)) { |
|
|
|
|
EXPECT_TRUE(false) |
|
|
|
|
<< "got unexpected event " |
|
|
|
|
<< (absl::holds_alternative<absl::Status>(event) |
|
|
|
|
? "error" |
|
|
|
|
: "does-not-exist") |
|
|
|
|
<< " at " << location.file() << ":" << location.line(); |
|
|
|
|
return absl::nullopt; |
|
|
|
|
while (true) { |
|
|
|
|
event_engine_->Tick(); |
|
|
|
|
MutexLock lock(&mu_); |
|
|
|
|
if (queue_.empty()) { |
|
|
|
|
if (event_engine_->IsIdle()) return absl::nullopt; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
Event& event = queue_.front(); |
|
|
|
|
if (!absl::holds_alternative<ResourceAndReadDelayHandle>(event)) { |
|
|
|
|
EXPECT_TRUE(false) |
|
|
|
|
<< "got unexpected event " |
|
|
|
|
<< (absl::holds_alternative<absl::Status>(event) |
|
|
|
|
? "error" |
|
|
|
|
: "does-not-exist") |
|
|
|
|
<< " at " << location.file() << ":" << location.line(); |
|
|
|
|
return absl::nullopt; |
|
|
|
|
} |
|
|
|
|
auto foo = std::move(absl::get<ResourceAndReadDelayHandle>(event)); |
|
|
|
|
queue_.pop_front(); |
|
|
|
|
return foo; |
|
|
|
|
} |
|
|
|
|
auto foo = std::move(absl::get<ResourceAndReadDelayHandle>(event)); |
|
|
|
|
queue_.pop_front(); |
|
|
|
|
return foo; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::shared_ptr<const ResourceStruct> WaitForNextResource( |
|
|
|
|
absl::Duration timeout = absl::Seconds(1), |
|
|
|
|
SourceLocation location = SourceLocation()) { |
|
|
|
|
auto resource_and_handle = |
|
|
|
|
WaitForNextResourceAndHandle(timeout, location); |
|
|
|
|
auto resource_and_handle = WaitForNextResourceAndHandle(location); |
|
|
|
|
if (!resource_and_handle.has_value()) { |
|
|
|
|
return nullptr; |
|
|
|
|
} |
|
|
|
@ -313,40 +323,50 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
absl::optional<absl::Status> WaitForNextError( |
|
|
|
|
absl::Duration timeout = absl::Seconds(1), |
|
|
|
|
SourceLocation location = SourceLocation()) { |
|
|
|
|
MutexLock lock(&mu_); |
|
|
|
|
if (!WaitForEventLocked(timeout)) return absl::nullopt; |
|
|
|
|
Event& event = queue_.front(); |
|
|
|
|
if (!absl::holds_alternative<absl::Status>(event)) { |
|
|
|
|
EXPECT_TRUE(false) |
|
|
|
|
<< "got unexpected event " |
|
|
|
|
<< (absl::holds_alternative<ResourceAndReadDelayHandle>(event) |
|
|
|
|
? "resource" |
|
|
|
|
: "does-not-exist") |
|
|
|
|
<< " at " << location.file() << ":" << location.line(); |
|
|
|
|
return absl::nullopt; |
|
|
|
|
while (true) { |
|
|
|
|
event_engine_->Tick(); |
|
|
|
|
MutexLock lock(&mu_); |
|
|
|
|
if (queue_.empty()) { |
|
|
|
|
if (event_engine_->IsIdle()) return absl::nullopt; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
Event& event = queue_.front(); |
|
|
|
|
if (!absl::holds_alternative<absl::Status>(event)) { |
|
|
|
|
EXPECT_TRUE(false) |
|
|
|
|
<< "got unexpected event " |
|
|
|
|
<< (absl::holds_alternative<ResourceAndReadDelayHandle>(event) |
|
|
|
|
? "resource" |
|
|
|
|
: "does-not-exist") |
|
|
|
|
<< " at " << location.file() << ":" << location.line(); |
|
|
|
|
return absl::nullopt; |
|
|
|
|
} |
|
|
|
|
absl::Status error = std::move(absl::get<absl::Status>(event)); |
|
|
|
|
queue_.pop_front(); |
|
|
|
|
return std::move(error); |
|
|
|
|
} |
|
|
|
|
absl::Status error = std::move(absl::get<absl::Status>(event)); |
|
|
|
|
queue_.pop_front(); |
|
|
|
|
return std::move(error); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool WaitForDoesNotExist(absl::Duration timeout, |
|
|
|
|
SourceLocation location = SourceLocation()) { |
|
|
|
|
MutexLock lock(&mu_); |
|
|
|
|
if (!WaitForEventLocked(timeout)) return false; |
|
|
|
|
Event& event = queue_.front(); |
|
|
|
|
if (!absl::holds_alternative<DoesNotExist>(event)) { |
|
|
|
|
EXPECT_TRUE(false) |
|
|
|
|
<< "got unexpected event " |
|
|
|
|
<< (absl::holds_alternative<absl::Status>(event) ? "error" |
|
|
|
|
: "resource") |
|
|
|
|
<< " at " << location.file() << ":" << location.line(); |
|
|
|
|
return false; |
|
|
|
|
bool WaitForDoesNotExist(SourceLocation location = SourceLocation()) { |
|
|
|
|
while (true) { |
|
|
|
|
event_engine_->Tick(); |
|
|
|
|
MutexLock lock(&mu_); |
|
|
|
|
if (queue_.empty()) { |
|
|
|
|
if (event_engine_->IsIdle()) return false; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
Event& event = queue_.front(); |
|
|
|
|
if (!absl::holds_alternative<DoesNotExist>(event)) { |
|
|
|
|
EXPECT_TRUE(false) |
|
|
|
|
<< "got unexpected event " |
|
|
|
|
<< (absl::holds_alternative<absl::Status>(event) ? "error" |
|
|
|
|
: "resource") |
|
|
|
|
<< " at " << location.file() << ":" << location.line(); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
queue_.pop_front(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
queue_.pop_front(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
@ -361,7 +381,6 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
ResourceAndReadDelayHandle event_details = { |
|
|
|
|
std::move(foo), std::move(read_delay_handle)}; |
|
|
|
|
queue_.emplace_back(std::move(event_details)); |
|
|
|
|
cv_.Signal(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void OnError( |
|
|
|
@ -370,7 +389,6 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
override { |
|
|
|
|
MutexLock lock(&mu_); |
|
|
|
|
queue_.push_back(std::move(status)); |
|
|
|
|
cv_.Signal(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void OnResourceDoesNotExist( |
|
|
|
@ -378,24 +396,11 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
override { |
|
|
|
|
MutexLock lock(&mu_); |
|
|
|
|
queue_.push_back(DoesNotExist()); |
|
|
|
|
cv_.Signal(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Returns true if an event was received, or false if the timeout
|
|
|
|
|
// expires before any event is received.
|
|
|
|
|
bool WaitForEventLocked(absl::Duration timeout) |
|
|
|
|
ABSL_EXCLUSIVE_LOCKS_REQUIRED(&mu_) { |
|
|
|
|
while (queue_.empty()) { |
|
|
|
|
if (cv_.WaitWithTimeout(&mu_, |
|
|
|
|
timeout * grpc_test_slowdown_factor())) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
std::shared_ptr<FuzzingEventEngine> event_engine_; |
|
|
|
|
|
|
|
|
|
Mutex mu_; |
|
|
|
|
CondVar cv_; |
|
|
|
|
std::deque<Event> queue_ ABSL_GUARDED_BY(&mu_); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -626,6 +631,9 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
uint64_t>; |
|
|
|
|
using ServerFailureMap = std::map<std::string /*xds_server*/, uint64_t>; |
|
|
|
|
|
|
|
|
|
explicit MetricsReporter(std::shared_ptr<FuzzingEventEngine> event_engine) |
|
|
|
|
: event_engine_(std::move(event_engine)) {} |
|
|
|
|
|
|
|
|
|
ResourceUpdateMap resource_updates_valid() const { |
|
|
|
|
MutexLock lock(&mu_); |
|
|
|
|
return resource_updates_valid_; |
|
|
|
@ -643,12 +651,10 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
::testing::Matcher<ResourceUpdateMap> resource_updates_valid_matcher, |
|
|
|
|
::testing::Matcher<ResourceUpdateMap> resource_updates_invalid_matcher, |
|
|
|
|
::testing::Matcher<ServerFailureMap> server_failures_matcher, |
|
|
|
|
absl::Duration timeout = absl::Seconds(3), |
|
|
|
|
SourceLocation location = SourceLocation()) { |
|
|
|
|
const absl::Time deadline = |
|
|
|
|
absl::Now() + (timeout * grpc_test_slowdown_factor()); |
|
|
|
|
MutexLock lock(&mu_); |
|
|
|
|
while (true) { |
|
|
|
|
event_engine_->Tick(); |
|
|
|
|
MutexLock lock(&mu_); |
|
|
|
|
if (::testing::Matches(resource_updates_valid_matcher)( |
|
|
|
|
resource_updates_valid_) && |
|
|
|
|
::testing::Matches(resource_updates_invalid_matcher)( |
|
|
|
@ -656,15 +662,15 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
::testing::Matches(server_failures_matcher)(server_failures_)) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
if (cond_.WaitWithDeadline(&mu_, deadline)) break; |
|
|
|
|
if (!event_engine_->IsIdle()) continue; |
|
|
|
|
EXPECT_THAT(resource_updates_valid_, resource_updates_valid_matcher) |
|
|
|
|
<< location.file() << ":" << location.line(); |
|
|
|
|
EXPECT_THAT(resource_updates_invalid_, resource_updates_invalid_matcher) |
|
|
|
|
<< location.file() << ":" << location.line(); |
|
|
|
|
EXPECT_THAT(server_failures_, server_failures_matcher) |
|
|
|
|
<< location.file() << ":" << location.line(); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
EXPECT_THAT(resource_updates_valid_, resource_updates_valid_matcher) |
|
|
|
|
<< location.file() << ":" << location.line(); |
|
|
|
|
EXPECT_THAT(resource_updates_invalid_, resource_updates_invalid_matcher) |
|
|
|
|
<< location.file() << ":" << location.line(); |
|
|
|
|
EXPECT_THAT(server_failures_, server_failures_matcher) |
|
|
|
|
<< location.file() << ":" << location.line(); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
@ -690,6 +696,8 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
cond_.SignalAll(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::shared_ptr<FuzzingEventEngine> event_engine_; |
|
|
|
|
|
|
|
|
|
mutable Mutex mu_; |
|
|
|
|
ResourceUpdateMap resource_updates_valid_ ABSL_GUARDED_BY(mu_); |
|
|
|
|
ResourceUpdateMap resource_updates_invalid_ ABSL_GUARDED_BY(mu_); |
|
|
|
@ -724,18 +732,35 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
return server_connection_map; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SetUp() override { |
|
|
|
|
event_engine_ = std::make_shared<FuzzingEventEngine>( |
|
|
|
|
FuzzingEventEngine::Options(), fuzzing_event_engine::Actions()); |
|
|
|
|
grpc_timer_manager_set_start_threaded(false); |
|
|
|
|
grpc_init(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void TearDown() override { |
|
|
|
|
transport_factory_.reset(); |
|
|
|
|
xds_client_.reset(); |
|
|
|
|
event_engine_->FuzzingDone(); |
|
|
|
|
event_engine_->TickUntilIdle(); |
|
|
|
|
event_engine_->UnsetGlobalHooks(); |
|
|
|
|
grpc_event_engine::experimental::WaitForSingleOwner( |
|
|
|
|
std::move(event_engine_)); |
|
|
|
|
grpc_shutdown_blocking(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Sets transport_factory_ and initializes xds_client_ with the
|
|
|
|
|
// specified bootstrap config.
|
|
|
|
|
void InitXdsClient( |
|
|
|
|
FakeXdsBootstrap::Builder bootstrap_builder = FakeXdsBootstrap::Builder(), |
|
|
|
|
Duration resource_request_timeout = Duration::Seconds(15)) { |
|
|
|
|
transport_factory_ = MakeRefCounted<FakeXdsTransportFactory>( |
|
|
|
|
[]() { FAIL() << "Multiple concurrent reads"; }); |
|
|
|
|
auto metrics_reporter = std::make_unique<MetricsReporter>(); |
|
|
|
|
[]() { FAIL() << "Multiple concurrent reads"; }, event_engine_); |
|
|
|
|
auto metrics_reporter = std::make_unique<MetricsReporter>(event_engine_); |
|
|
|
|
metrics_reporter_ = metrics_reporter.get(); |
|
|
|
|
xds_client_ = MakeRefCounted<XdsClient>( |
|
|
|
|
bootstrap_builder.Build(), transport_factory_, |
|
|
|
|
grpc_event_engine::experimental::GetDefaultEventEngine(), |
|
|
|
|
bootstrap_builder.Build(), transport_factory_, event_engine_, |
|
|
|
|
std::move(metrics_reporter), "foo agent", "foo version", |
|
|
|
|
resource_request_timeout * grpc_test_slowdown_factor()); |
|
|
|
|
} |
|
|
|
@ -743,7 +768,7 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
// Starts and cancels a watch for a Foo resource.
|
|
|
|
|
RefCountedPtr<XdsFooResourceType::Watcher> StartFooWatch( |
|
|
|
|
absl::string_view resource_name) { |
|
|
|
|
auto watcher = MakeRefCounted<XdsFooResourceType::Watcher>(); |
|
|
|
|
auto watcher = MakeRefCounted<XdsFooResourceType::Watcher>(event_engine_); |
|
|
|
|
XdsFooResourceType::StartWatch(xds_client_.get(), resource_name, watcher); |
|
|
|
|
return watcher; |
|
|
|
|
} |
|
|
|
@ -757,7 +782,7 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
// Starts and cancels a watch for a Bar resource.
|
|
|
|
|
RefCountedPtr<XdsBarResourceType::Watcher> StartBarWatch( |
|
|
|
|
absl::string_view resource_name) { |
|
|
|
|
auto watcher = MakeRefCounted<XdsBarResourceType::Watcher>(); |
|
|
|
|
auto watcher = MakeRefCounted<XdsBarResourceType::Watcher>(event_engine_); |
|
|
|
|
XdsBarResourceType::StartWatch(xds_client_.get(), resource_name, watcher); |
|
|
|
|
return watcher; |
|
|
|
|
} |
|
|
|
@ -771,7 +796,8 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
// Starts and cancels a watch for a WildcardCapable resource.
|
|
|
|
|
RefCountedPtr<XdsWildcardCapableResourceType::Watcher> |
|
|
|
|
StartWildcardCapableWatch(absl::string_view resource_name) { |
|
|
|
|
auto watcher = MakeRefCounted<XdsWildcardCapableResourceType::Watcher>(); |
|
|
|
|
auto watcher = |
|
|
|
|
MakeRefCounted<XdsWildcardCapableResourceType::Watcher>(event_engine_); |
|
|
|
|
XdsWildcardCapableResourceType::StartWatch(xds_client_.get(), resource_name, |
|
|
|
|
watcher); |
|
|
|
|
return watcher; |
|
|
|
@ -784,11 +810,13 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
RefCountedPtr<FakeXdsTransportFactory::FakeStreamingCall> WaitForAdsStream( |
|
|
|
|
const XdsBootstrap::XdsServer& xds_server, |
|
|
|
|
absl::Duration timeout = absl::Seconds(5)) { |
|
|
|
|
const XdsBootstrap::XdsServer& xds_server) { |
|
|
|
|
return transport_factory_->WaitForStream( |
|
|
|
|
xds_server, FakeXdsTransportFactory::kAdsMethod, |
|
|
|
|
timeout * grpc_test_slowdown_factor()); |
|
|
|
|
xds_server, FakeXdsTransportFactory::kAdsMethod); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
RefCountedPtr<FakeXdsTransportFactory::FakeStreamingCall> WaitForAdsStream() { |
|
|
|
|
return WaitForAdsStream(*xds_client_->bootstrap().servers().front()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void TriggerConnectionFailure(const XdsBootstrap::XdsServer& xds_server, |
|
|
|
@ -796,19 +824,11 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
transport_factory_->TriggerConnectionFailure(xds_server, std::move(status)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
RefCountedPtr<FakeXdsTransportFactory::FakeStreamingCall> WaitForAdsStream( |
|
|
|
|
absl::Duration timeout = absl::Seconds(5)) { |
|
|
|
|
return WaitForAdsStream(*xds_client_->bootstrap().servers().front(), |
|
|
|
|
timeout); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Gets the latest request sent to the fake xDS server.
|
|
|
|
|
absl::optional<DiscoveryRequest> WaitForRequest( |
|
|
|
|
FakeXdsTransportFactory::FakeStreamingCall* stream, |
|
|
|
|
absl::Duration timeout = absl::Seconds(3), |
|
|
|
|
SourceLocation location = SourceLocation()) { |
|
|
|
|
auto message = |
|
|
|
|
stream->WaitForMessageFromClient(timeout * grpc_test_slowdown_factor()); |
|
|
|
|
auto message = stream->WaitForMessageFromClient(); |
|
|
|
|
if (!message.has_value()) return absl::nullopt; |
|
|
|
|
DiscoveryRequest request; |
|
|
|
|
bool success = request.ParseFromString(*message); |
|
|
|
@ -893,6 +913,7 @@ class XdsClientTest : public ::testing::Test { |
|
|
|
|
<< location.file() << ":" << location.line(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::shared_ptr<FuzzingEventEngine> event_engine_; |
|
|
|
|
RefCountedPtr<FakeXdsTransportFactory> transport_factory_; |
|
|
|
|
RefCountedPtr<XdsClient> xds_client_; |
|
|
|
|
MetricsReporter* metrics_reporter_ = nullptr; |
|
|
|
@ -2011,7 +2032,7 @@ TEST_F(XdsClientTest, ResourceDeletion) { |
|
|
|
|
.set_nonce("B") |
|
|
|
|
.Serialize()); |
|
|
|
|
// Watcher should see the does-not-exist event.
|
|
|
|
|
EXPECT_TRUE(watcher->WaitForDoesNotExist(absl::Seconds(1))); |
|
|
|
|
EXPECT_TRUE(watcher->WaitForDoesNotExist()); |
|
|
|
|
// Check metric data.
|
|
|
|
|
EXPECT_TRUE(metrics_reporter_->WaitForMetricsReporterData( |
|
|
|
|
::testing::ElementsAre(::testing::Pair( |
|
|
|
@ -2029,7 +2050,7 @@ TEST_F(XdsClientTest, ResourceDeletion) { |
|
|
|
|
// Start a new watcher for the same resource. It should immediately
|
|
|
|
|
// receive the same does-not-exist notification.
|
|
|
|
|
auto watcher2 = StartWildcardCapableWatch("wc1"); |
|
|
|
|
EXPECT_TRUE(watcher2->WaitForDoesNotExist(absl::Seconds(1))); |
|
|
|
|
EXPECT_TRUE(watcher2->WaitForDoesNotExist()); |
|
|
|
|
// XdsClient should have sent an ACK message to the xDS server.
|
|
|
|
|
request = WaitForRequest(stream.get()); |
|
|
|
|
ASSERT_TRUE(request.has_value()); |
|
|
|
@ -2142,7 +2163,7 @@ TEST_F(XdsClientTest, ResourceDeletionIgnoredWhenConfigured) { |
|
|
|
|
.Serialize()); |
|
|
|
|
// Watcher should not see any update, since we should have ignored the
|
|
|
|
|
// deletion.
|
|
|
|
|
EXPECT_TRUE(watcher->ExpectNoEvent(absl::Seconds(1))); |
|
|
|
|
EXPECT_TRUE(watcher->ExpectNoEvent()); |
|
|
|
|
// Check metric data.
|
|
|
|
|
EXPECT_TRUE(metrics_reporter_->WaitForMetricsReporterData( |
|
|
|
|
::testing::ElementsAre(::testing::Pair( |
|
|
|
@ -2438,7 +2459,7 @@ TEST_F(XdsClientTest, ConnectionFails) { |
|
|
|
|
::testing::ElementsAre(::testing::Pair(kDefaultXdsServerUrl, 1)))); |
|
|
|
|
// We should not see a resource-does-not-exist event, because the
|
|
|
|
|
// timer should not be running while the channel is disconnected.
|
|
|
|
|
EXPECT_TRUE(watcher->ExpectNoEvent(absl::Seconds(4))); |
|
|
|
|
EXPECT_TRUE(watcher->ExpectNoEvent()); |
|
|
|
|
// Start a new watch. This watcher should be given the same error,
|
|
|
|
|
// since we have not yet recovered.
|
|
|
|
|
auto watcher2 = StartFooWatch("foo1"); |
|
|
|
@ -2517,7 +2538,7 @@ TEST_F(XdsClientTest, ResourceDoesNotExistUponTimeout) { |
|
|
|
|
CheckRequestNode(*request); // Should be present on the first request.
|
|
|
|
|
// Do not send a response, but wait for the resource to be reported as
|
|
|
|
|
// not existing.
|
|
|
|
|
EXPECT_TRUE(watcher->WaitForDoesNotExist(absl::Seconds(5))); |
|
|
|
|
EXPECT_TRUE(watcher->WaitForDoesNotExist()); |
|
|
|
|
// Check metric data.
|
|
|
|
|
EXPECT_TRUE(metrics_reporter_->WaitForMetricsReporterData( |
|
|
|
|
::testing::ElementsAre(), ::testing::ElementsAre(), ::testing::_)); |
|
|
|
@ -2530,7 +2551,7 @@ TEST_F(XdsClientTest, ResourceDoesNotExistUponTimeout) { |
|
|
|
|
// Start a new watcher for the same resource. It should immediately
|
|
|
|
|
// receive the same does-not-exist notification.
|
|
|
|
|
auto watcher2 = StartFooWatch("foo1"); |
|
|
|
|
EXPECT_TRUE(watcher2->WaitForDoesNotExist(absl::Seconds(1))); |
|
|
|
|
EXPECT_TRUE(watcher2->WaitForDoesNotExist()); |
|
|
|
|
// Now server sends a response.
|
|
|
|
|
stream->SendMessageToClient( |
|
|
|
|
ResponseBuilder(XdsFooResourceType::Get()->type_url()) |
|
|
|
@ -2641,7 +2662,7 @@ TEST_F(XdsClientTest, ResourceDoesNotExistAfterStreamRestart) { |
|
|
|
|
CheckRequestNode(*request); // Should be present on the first request.
|
|
|
|
|
// Server does NOT send a response immediately.
|
|
|
|
|
// Client should receive a resource does-not-exist.
|
|
|
|
|
ASSERT_TRUE(watcher->WaitForDoesNotExist(absl::Seconds(4))); |
|
|
|
|
ASSERT_TRUE(watcher->WaitForDoesNotExist()); |
|
|
|
|
// Check metric data.
|
|
|
|
|
EXPECT_TRUE(metrics_reporter_->WaitForMetricsReporterData( |
|
|
|
|
::testing::ElementsAre(), ::testing::ElementsAre(), ::testing::_)); |
|
|
|
@ -2713,7 +2734,7 @@ TEST_F(XdsClientTest, DoesNotExistTimerNotStartedUntilSendCompletes) { |
|
|
|
|
// Server does NOT send a response.
|
|
|
|
|
// We should not see a resource-does-not-exist event, because the
|
|
|
|
|
// timer should not be running while the channel is disconnected.
|
|
|
|
|
EXPECT_TRUE(watcher->ExpectNoEvent(absl::Seconds(4))); |
|
|
|
|
EXPECT_TRUE(watcher->ExpectNoEvent()); |
|
|
|
|
// Check metric data.
|
|
|
|
|
EXPECT_THAT(GetResourceCounts(), |
|
|
|
|
::testing::ElementsAre(::testing::Pair( |
|
|
|
@ -2726,7 +2747,7 @@ TEST_F(XdsClientTest, DoesNotExistTimerNotStartedUntilSendCompletes) { |
|
|
|
|
stream->CompleteSendMessageFromClient(); |
|
|
|
|
// Server does NOT send a response.
|
|
|
|
|
// Watcher should see a does-not-exist event.
|
|
|
|
|
EXPECT_TRUE(watcher->WaitForDoesNotExist(absl::Seconds(4))); |
|
|
|
|
EXPECT_TRUE(watcher->WaitForDoesNotExist()); |
|
|
|
|
// Check metric data.
|
|
|
|
|
EXPECT_THAT(GetResourceCounts(), |
|
|
|
|
::testing::ElementsAre(::testing::Pair( |
|
|
|
@ -2915,7 +2936,7 @@ TEST_F(XdsClientTest, |
|
|
|
|
/*resource_names=*/{"foo1", "foo2"}); |
|
|
|
|
stream->CompleteSendMessageFromClient(); |
|
|
|
|
// Make sure the watcher for foo1 does not see a does-not-exist event.
|
|
|
|
|
EXPECT_TRUE(watcher->ExpectNoEvent(absl::Seconds(5))); |
|
|
|
|
EXPECT_TRUE(watcher->ExpectNoEvent()); |
|
|
|
|
// Cancel watches.
|
|
|
|
|
CancelFooWatch(watcher.get(), "foo1", /*delay_unsubscription=*/true); |
|
|
|
|
CancelFooWatch(watcher2.get(), "foo2"); |
|
|
|
@ -2992,7 +3013,7 @@ TEST_F(XdsClientTest, DoNotSendDoesNotExistForCachedResource) { |
|
|
|
|
// We should not see a resource-does-not-exist event, because the
|
|
|
|
|
// resource was already cached, so the server can optimize by not
|
|
|
|
|
// resending it.
|
|
|
|
|
EXPECT_TRUE(watcher->ExpectNoEvent(absl::Seconds(4))); |
|
|
|
|
EXPECT_TRUE(watcher->ExpectNoEvent()); |
|
|
|
|
// Check metric data.
|
|
|
|
|
EXPECT_TRUE(metrics_reporter_->WaitForMetricsReporterData( |
|
|
|
|
::testing::ElementsAre(::testing::Pair( |
|
|
|
@ -3014,7 +3035,7 @@ TEST_F(XdsClientTest, DoNotSendDoesNotExistForCachedResource) { |
|
|
|
|
.AddFooResource(XdsFooResource("foo1", 6)) |
|
|
|
|
.Serialize()); |
|
|
|
|
// Watcher will not see any update, since the resource is unchanged.
|
|
|
|
|
EXPECT_TRUE(watcher->ExpectNoEvent(absl::Seconds(1))); |
|
|
|
|
EXPECT_TRUE(watcher->ExpectNoEvent()); |
|
|
|
|
// Check metric data.
|
|
|
|
|
EXPECT_TRUE(metrics_reporter_->WaitForMetricsReporterData( |
|
|
|
|
::testing::ElementsAre(::testing::Pair( |
|
|
|
@ -3504,7 +3525,7 @@ TEST_F(XdsClientTest, FederationWithUnknownAuthority) { |
|
|
|
|
<< *error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_F(XdsClientTest, FederationWithUnparsableXdstpResourceName) { |
|
|
|
|
TEST_F(XdsClientTest, FederationWithUnparseableXdstpResourceName) { |
|
|
|
|
// Note: Not adding authority to bootstrap config.
|
|
|
|
|
InitXdsClient(); |
|
|
|
|
// Start a watch for the xdstp resource name.
|
|
|
|
@ -3724,7 +3745,6 @@ TEST_F(XdsClientTest, FederationChannelFailureReportedToWatchers) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_F(XdsClientTest, AdsReadWaitsForHandleRelease) { |
|
|
|
|
const absl::Duration timeout = absl::Seconds(5) * grpc_test_slowdown_factor(); |
|
|
|
|
InitXdsClient(); |
|
|
|
|
// Start watches for "foo1" and "foo2".
|
|
|
|
|
auto watcher1 = StartFooWatch("foo1"); |
|
|
|
@ -3777,11 +3797,11 @@ TEST_F(XdsClientTest, AdsReadWaitsForHandleRelease) { |
|
|
|
|
/*version_info=*/"1", /*response_nonce=*/"A", |
|
|
|
|
/*error_detail=*/absl::OkStatus(), |
|
|
|
|
/*resource_names=*/{"foo1", "foo2"}); |
|
|
|
|
EXPECT_TRUE(stream->WaitForReadsStarted(1, timeout)); |
|
|
|
|
EXPECT_TRUE(stream->WaitForReadsStarted(1)); |
|
|
|
|
resource1->read_delay_handle.reset(); |
|
|
|
|
EXPECT_TRUE(stream->WaitForReadsStarted(1, timeout)); |
|
|
|
|
EXPECT_TRUE(stream->WaitForReadsStarted(1)); |
|
|
|
|
resource2->read_delay_handle.reset(); |
|
|
|
|
EXPECT_TRUE(stream->WaitForReadsStarted(2, timeout)); |
|
|
|
|
EXPECT_TRUE(stream->WaitForReadsStarted(2)); |
|
|
|
|
resource1 = watcher1->WaitForNextResourceAndHandle(); |
|
|
|
|
ASSERT_NE(resource1, absl::nullopt); |
|
|
|
|
EXPECT_EQ(resource1->resource->name, "foo1"); |
|
|
|
@ -3794,9 +3814,9 @@ TEST_F(XdsClientTest, AdsReadWaitsForHandleRelease) { |
|
|
|
|
/*version_info=*/"2", /*response_nonce=*/"B", |
|
|
|
|
/*error_detail=*/absl::OkStatus(), |
|
|
|
|
/*resource_names=*/{"foo1", "foo2"}); |
|
|
|
|
EXPECT_TRUE(stream->WaitForReadsStarted(2, timeout)); |
|
|
|
|
EXPECT_TRUE(stream->WaitForReadsStarted(2)); |
|
|
|
|
resource1->read_delay_handle.reset(); |
|
|
|
|
EXPECT_TRUE(stream->WaitForReadsStarted(3, timeout)); |
|
|
|
|
EXPECT_TRUE(stream->WaitForReadsStarted(3)); |
|
|
|
|
// Cancel watch.
|
|
|
|
|
CancelFooWatch(watcher1.get(), "foo1"); |
|
|
|
|
request = WaitForRequest(stream.get()); |
|
|
|
@ -4185,8 +4205,5 @@ TEST_F(XdsClientTest, FallbackOnStartup) { |
|
|
|
|
int main(int argc, char** argv) { |
|
|
|
|
::testing::InitGoogleTest(&argc, argv); |
|
|
|
|
grpc::testing::TestEnvironment env(&argc, argv); |
|
|
|
|
grpc_init(); |
|
|
|
|
int ret = RUN_ALL_TESTS(); |
|
|
|
|
grpc_shutdown(); |
|
|
|
|
return ret; |
|
|
|
|
return RUN_ALL_TESTS(); |
|
|
|
|
} |
|
|
|
|