xref: /aosp_15_r20/external/grpc-grpc/test/cpp/interop/xds_stats_watcher_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 // Copyright 2023 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "test/cpp/interop/xds_stats_watcher.h"
18 
19 #include <map>
20 #include <memory>
21 
22 #include <gmock/gmock.h>
23 #include <gtest/gtest.h>
24 
25 #include <grpc/grpc.h>
26 
27 #include "test/core/util/test_config.h"
28 
29 namespace grpc {
30 namespace testing {
31 namespace {
32 
BuildCallResult(int saved_request_id)33 AsyncClientCallResult BuildCallResult(int saved_request_id) {
34   AsyncClientCallResult result;
35   result.saved_request_id = saved_request_id;
36   result.rpc_type = ClientConfigureRequest::UNARY_CALL;
37   return result;
38 }
39 
40 struct MetadataEntryInit {
41   absl::string_view key;
42   absl::string_view value;
43   bool is_trailing;
44 };
45 
BuildMetadatas(const std::initializer_list<std::initializer_list<MetadataEntryInit>> & values)46 LoadBalancerStatsResponse::MetadataByPeer BuildMetadatas(
47     const std::initializer_list<std::initializer_list<MetadataEntryInit>>&
48         values) {
49   LoadBalancerStatsResponse::MetadataByPeer metadata_by_peer;
50   for (const auto& per_rpc : values) {
51     auto rpc_metadata = metadata_by_peer.add_rpc_metadata();
52     for (const auto& key_value : per_rpc) {
53       auto entry = rpc_metadata->add_metadata();
54       entry->set_key(key_value.key);
55       entry->set_value(key_value.value);
56       entry->set_type(key_value.is_trailing
57                           ? LoadBalancerStatsResponse::TRAILING
58                           : LoadBalancerStatsResponse::INITIAL);
59     }
60   }
61   return metadata_by_peer;
62 }
63 
TEST(XdsStatsWatcherTest,WaitForRpcStatsResponse)64 TEST(XdsStatsWatcherTest, WaitForRpcStatsResponse) {
65   // "k3" will be ignored
66   XdsStatsWatcher watcher(0, 4, {"k1", "k2"});
67   watcher.RpcCompleted(BuildCallResult(0), "peer1",
68                        {{"k1", "v1"}, {"k2", "v2"}, {"k3", "v3"}},
69                        {{"k1", "t1"}, {"k3", "t3"}});
70   watcher.RpcCompleted(BuildCallResult(1), "peer1", {{"k1", "v4"}}, {});
71   watcher.RpcCompleted(BuildCallResult(2), "peer1", {}, {});
72   watcher.RpcCompleted(BuildCallResult(3), "peer2",
73                        {{"k1", "v5"}, {"k2", "v6"}, {"k3", "v7"}},
74                        {{"k1", "t5"}, {"k3", "t7"}});
75   LoadBalancerStatsResponse expected;
76   expected.mutable_rpcs_by_peer()->insert({{"peer1", 3}, {"peer2", 1}});
77   expected.mutable_metadatas_by_peer()->insert({
78       {"peer1",
79        BuildMetadatas({
80            {{"k1", "v1", false}, {"k2", "v2", false}, {"k1", "t1", true}},
81            {{"k1", "v4", false}},
82            {},
83        })},
84       {"peer2",
85        BuildMetadatas({
86            {{"k1", "v5", false}, {"k2", "v6", false}, {"k1", "t5", true}},
87        })},
88   });
89   (*expected.mutable_rpcs_by_method())["UnaryCall"]
90       .mutable_rpcs_by_peer()
91       ->insert({{"peer1", 3}, {"peer2", 1}});
92   EXPECT_EQ(expected.DebugString(),
93             watcher.WaitForRpcStatsResponse(0).DebugString());
94 }
95 
TEST(XdsStatsWatcherTest,WaitForRpcStatsResponseIgnoresCase)96 TEST(XdsStatsWatcherTest, WaitForRpcStatsResponseIgnoresCase) {
97   // "k3" will be ignored
98   XdsStatsWatcher watcher(0, 3, {"k1", "K2"});
99   watcher.RpcCompleted(BuildCallResult(0), "peer1",
100                        {{"K1", "v1"}, {"k2", "v2"}, {"k3", "v3"}},
101                        {{"K1", "t1"}, {"k2", "t2"}});
102   watcher.RpcCompleted(BuildCallResult(1), "peer1", {}, {});
103   watcher.RpcCompleted(BuildCallResult(2), "peer2", {},
104                        {{"k1", "v5"}, {"K2", "v6"}, {"k3", "v7"}});
105   LoadBalancerStatsResponse expected;
106   expected.mutable_rpcs_by_peer()->insert({{"peer1", 2}, {"peer2", 1}});
107   expected.mutable_metadatas_by_peer()->insert({
108       {"peer1", BuildMetadatas({
109                     {{"K1", "v1", false},
110                      {"k2", "v2", false},
111                      {"K1", "t1", true},
112                      {"k2", "t2", true}},
113                     {},
114                 })},
115       {"peer2", BuildMetadatas({{{"K2", "v6", true}, {"k1", "v5", true}}})},
116   });
117   (*expected.mutable_rpcs_by_method())["UnaryCall"]
118       .mutable_rpcs_by_peer()
119       ->insert({{"peer1", 2}, {"peer2", 1}});
120   EXPECT_EQ(expected.DebugString(),
121             watcher.WaitForRpcStatsResponse(0).DebugString());
122 }
123 
TEST(XdsStatsWatcherTest,WaitForRpcStatsResponseReturnsAll)124 TEST(XdsStatsWatcherTest, WaitForRpcStatsResponseReturnsAll) {
125   // "k3" will be ignored
126   XdsStatsWatcher watcher(0, 3, {"*"});
127   watcher.RpcCompleted(BuildCallResult(0), "peer1",
128                        {{"K1", "v1"}, {"k2", "v2"}, {"k3", "v3"}},
129                        {{"K1", "t1"}, {"k2", "t2"}});
130   watcher.RpcCompleted(BuildCallResult(1), "peer1", {}, {});
131   watcher.RpcCompleted(BuildCallResult(2), "peer2", {},
132                        {{"k1", "v5"}, {"K2", "v6"}, {"k3", "v7"}});
133   LoadBalancerStatsResponse expected;
134   expected.mutable_rpcs_by_peer()->insert({{"peer1", 2}, {"peer2", 1}});
135   expected.mutable_metadatas_by_peer()->insert({
136       {"peer1", BuildMetadatas({
137                     {{"K1", "v1", false},
138                      {"k2", "v2", false},
139                      {"k3", "v3", false},
140                      {"K1", "t1", true},
141                      {"k2", "t2", true}},
142                     {},
143                 })},
144       {"peer2",
145        BuildMetadatas(
146            {{{"K2", "v6", true}, {"k1", "v5", true}, {"k3", "v7", true}}})},
147   });
148   (*expected.mutable_rpcs_by_method())["UnaryCall"]
149       .mutable_rpcs_by_peer()
150       ->insert({{"peer1", 2}, {"peer2", 1}});
151   EXPECT_EQ(expected.DebugString(),
152             watcher.WaitForRpcStatsResponse(0).DebugString());
153 }
154 
TEST(XdsStatsWatcherTest,WaitForRpcStatsResponseExcludesMetadata)155 TEST(XdsStatsWatcherTest, WaitForRpcStatsResponseExcludesMetadata) {
156   XdsStatsWatcher watcher(0, 3, {});
157   // RPC had metadata - but watcher should ignore it
158   watcher.RpcCompleted(BuildCallResult(0), "peer1",
159                        {{"K1", "v1"}, {"k2", "v2"}, {"k3", "v3"}},
160                        {{"K1", "t1"}, {"k2", "t2"}});
161   watcher.RpcCompleted(BuildCallResult(1), "peer1", {{"k1", "v4"}}, {});
162   watcher.RpcCompleted(BuildCallResult(2), "peer2", {},
163                        {{"k1", "v5"}, {"k2", "v6"}, {"k3", "v7"}});
164   LoadBalancerStatsResponse expected;
165   expected.mutable_rpcs_by_peer()->insert({{"peer1", 2}, {"peer2", 1}});
166   (*expected.mutable_rpcs_by_method())["UnaryCall"]
167       .mutable_rpcs_by_peer()
168       ->insert({{"peer1", 2}, {"peer2", 1}});
169   EXPECT_EQ(watcher.WaitForRpcStatsResponse(0).DebugString(),
170             expected.DebugString());
171 }
172 
173 }  // namespace
174 }  // namespace testing
175 }  // namespace grpc
176 
main(int argc,char ** argv)177 int main(int argc, char** argv) {
178   ::testing::InitGoogleTest(&argc, argv);
179   grpc::testing::TestEnvironment env(&argc, argv);
180   grpc_init();
181   auto result = RUN_ALL_TESTS();
182   grpc_shutdown();
183   return result;
184 }
185