aboutsummaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
authorGravatar ncteisen <ncteisen@gmail.com>2018-06-28 00:12:02 -0700
committerGravatar ncteisen <ncteisen@gmail.com>2018-06-28 00:12:02 -0700
commit8db7788d46fcdf9f35e8708e3b04bc4753f9f288 (patch)
treed321282205f58aa6dad45c29f4c3ab9331553436 /test
parent0d878eae6cedf32e6e77e02f4c29ec232b41eb63 (diff)
parent28512108da77ccbc7954642c71312425744dfe19 (diff)
Merge branch 'master' of https://github.com/grpc/grpc into serialization
Diffstat (limited to 'test')
-rw-r--r--test/build/no-c++14-compat.cc19
-rw-r--r--test/build/no-maybe-uninitialized.c19
-rw-r--r--test/build/no-unused-but-set-variable.c19
-rw-r--r--test/core/channel/BUILD17
-rw-r--r--test/core/channel/channel_trace_test.cc196
-rw-r--r--test/core/channel/channelz_test.cc216
-rw-r--r--test/core/end2end/end2end_nosec_tests.cc16
-rw-r--r--test/core/end2end/end2end_tests.cc16
-rw-r--r--test/core/end2end/fixtures/h2_load_reporting.cc120
-rw-r--r--test/core/end2end/fuzzers/api_fuzzer.cc1
-rwxr-xr-xtest/core/end2end/gen_build_yaml.py9
-rwxr-xr-xtest/core/end2end/generate_tests.bzl10
-rw-r--r--test/core/end2end/tests/channelz.cc299
-rw-r--r--test/core/iomgr/BUILD21
-rw-r--r--test/core/iomgr/ev_epollex_linux_test.cc115
-rw-r--r--test/core/surface/public_headers_must_be_c89.c2
-rw-r--r--test/cpp/microbenchmarks/BUILD14
-rw-r--r--test/cpp/microbenchmarks/bm_call_create.cc11
-rw-r--r--test/cpp/microbenchmarks/bm_channel.cc90
-rw-r--r--test/cpp/naming/cancel_ares_query_test.cc46
-rw-r--r--test/cpp/server/load_reporter/BUILD34
-rw-r--r--test/cpp/server/load_reporter/get_cpu_stats_test.cc61
-rw-r--r--test/cpp/server/load_reporter/load_data_store_test.cc4
-rw-r--r--test/cpp/server/load_reporter/load_reporter_test.cc498
-rw-r--r--test/cpp/util/channel_trace_proto_helper.cc41
-rw-r--r--test/cpp/util/channel_trace_proto_helper.h1
-rwxr-xr-xtest/distrib/python/test_packages.sh16
27 files changed, 1640 insertions, 271 deletions
diff --git a/test/build/no-c++14-compat.cc b/test/build/no-c++14-compat.cc
new file mode 100644
index 0000000000..0c1771c7bb
--- /dev/null
+++ b/test/build/no-c++14-compat.cc
@@ -0,0 +1,19 @@
+/*
+ *
+ * Copyright 2015 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.
+ *
+ */
+
+int main(void) {}
diff --git a/test/build/no-maybe-uninitialized.c b/test/build/no-maybe-uninitialized.c
new file mode 100644
index 0000000000..0c1771c7bb
--- /dev/null
+++ b/test/build/no-maybe-uninitialized.c
@@ -0,0 +1,19 @@
+/*
+ *
+ * Copyright 2015 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.
+ *
+ */
+
+int main(void) {}
diff --git a/test/build/no-unused-but-set-variable.c b/test/build/no-unused-but-set-variable.c
new file mode 100644
index 0000000000..0c1771c7bb
--- /dev/null
+++ b/test/build/no-unused-but-set-variable.c
@@ -0,0 +1,19 @@
+/*
+ *
+ * Copyright 2015 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.
+ *
+ */
+
+int main(void) {}
diff --git a/test/core/channel/BUILD b/test/core/channel/BUILD
index e5a9e36457..da419f00cf 100644
--- a/test/core/channel/BUILD
+++ b/test/core/channel/BUILD
@@ -84,6 +84,23 @@ grpc_cc_test(
)
grpc_cc_test(
+ name = "channelz_test",
+ srcs = ["channelz_test.cc"],
+ language = "C++",
+ deps = [
+ "//:gpr",
+ "//:grpc",
+ "//:grpc++",
+ "//test/core/util:gpr_test_util",
+ "//test/core/util:grpc_test_util",
+ "//test/cpp/util:channel_trace_proto_helper",
+ ],
+ external_deps = [
+ "gtest",
+ ],
+)
+
+grpc_cc_test(
name = "channelz_registry_test",
srcs = ["channelz_registry_test.cc"],
language = "C++",
diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc
index d99a32d91d..bbddee3f14 100644
--- a/test/core/channel/channel_trace_test.cc
+++ b/test/core/channel/channel_trace_test.cc
@@ -25,6 +25,7 @@
#include <grpc/support/log.h>
#include "src/core/lib/channel/channel_trace.h"
+#include "src/core/lib/channel/channelz.h"
#include "src/core/lib/channel/channelz_registry.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/iomgr/exec_ctx.h"
@@ -39,6 +40,7 @@
#include <string.h>
namespace grpc_core {
+namespace channelz {
namespace testing {
namespace {
@@ -69,7 +71,7 @@ void ValidateChannelTraceData(grpc_json* json,
ASSERT_NE(json, nullptr);
grpc_json* num_events_logged_json = GetJsonChild(json, "numEventsLogged");
ASSERT_NE(num_events_logged_json, nullptr);
- grpc_json* start_time = GetJsonChild(json, "creationTime");
+ grpc_json* start_time = GetJsonChild(json, "creationTimestamp");
ASSERT_NE(start_time, nullptr);
size_t num_events_logged =
(size_t)strtol(num_events_logged_json->value, nullptr, 0);
@@ -77,35 +79,47 @@ void ValidateChannelTraceData(grpc_json* json,
ValidateJsonArraySize(json, "events", actual_num_events_expected);
}
-void AddSimpleTrace(const RefCountedPtr<ChannelTrace>& tracer) {
+void AddSimpleTrace(ChannelTrace* tracer) {
tracer->AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("simple trace"));
}
// checks for the existence of all the required members of the tracer.
-void ValidateChannelTrace(const RefCountedPtr<ChannelTrace>& tracer,
+void ValidateChannelTrace(ChannelTrace* tracer,
size_t expected_num_event_logged, size_t max_nodes) {
if (!max_nodes) return;
- char* json_str = tracer->RenderTrace();
+ grpc_json* json = tracer->RenderJSON();
+ EXPECT_NE(json, nullptr);
+ char* json_str = grpc_json_dump_to_string(json, 0);
+ grpc_json_destroy(json);
grpc::testing::ValidateChannelTraceProtoJsonTranslation(json_str);
- grpc_json* json = grpc_json_parse_string(json_str);
- ValidateChannelTraceData(json, expected_num_event_logged,
+ grpc_json* parsed_json = grpc_json_parse_string(json_str);
+ ValidateChannelTraceData(parsed_json, expected_num_event_logged,
GPR_MIN(expected_num_event_logged, max_nodes));
- grpc_json_destroy(json);
+ grpc_json_destroy(parsed_json);
gpr_free(json_str);
}
-void ValidateTraceDataMatchedUuidLookup(
- const RefCountedPtr<ChannelTrace>& tracer) {
- intptr_t uuid = tracer->GetUuid();
- if (uuid == -1) return; // Doesn't make sense to lookup if tracing disabled
- char* tracer_json_str = tracer->RenderTrace();
- ChannelTrace* uuid_lookup = ChannelzRegistry::Get<ChannelTrace>(uuid);
- char* uuid_lookup_json_str = uuid_lookup->RenderTrace();
- EXPECT_EQ(strcmp(tracer_json_str, uuid_lookup_json_str), 0);
- gpr_free(tracer_json_str);
- gpr_free(uuid_lookup_json_str);
-}
+class ChannelFixture {
+ public:
+ ChannelFixture(int max_trace_nodes) {
+ grpc_arg client_a;
+ client_a.type = GRPC_ARG_INTEGER;
+ client_a.key =
+ const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE);
+ client_a.value.integer = max_trace_nodes;
+ grpc_channel_args client_args = {1, &client_a};
+ channel_ =
+ grpc_insecure_channel_create("fake_target", &client_args, nullptr);
+ }
+
+ ~ChannelFixture() { grpc_channel_destroy(channel_); }
+
+ grpc_channel* channel() { return channel_; }
+
+ private:
+ grpc_channel* channel_;
+};
} // anonymous namespace
@@ -115,25 +129,22 @@ class ChannelTracerTest : public ::testing::TestWithParam<size_t> {};
// lookups by uuid.
TEST_P(ChannelTracerTest, BasicTest) {
grpc_core::ExecCtx exec_ctx;
- RefCountedPtr<ChannelTrace> tracer = MakeRefCounted<ChannelTrace>(GetParam());
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- ValidateTraceDataMatchedUuidLookup(tracer);
- tracer->AddTraceEvent(ChannelTrace::Severity::Info,
- grpc_slice_from_static_string("trace three"));
- tracer->AddTraceEvent(ChannelTrace::Severity::Error,
- grpc_slice_from_static_string("trace four error"));
- ValidateChannelTrace(tracer, 4, GetParam());
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- ValidateChannelTrace(tracer, 6, GetParam());
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- ValidateChannelTrace(tracer, 10, GetParam());
- ValidateTraceDataMatchedUuidLookup(tracer);
- tracer.reset(nullptr);
+ ChannelTrace tracer(GetParam());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ tracer.AddTraceEvent(ChannelTrace::Severity::Info,
+ grpc_slice_from_static_string("trace three"));
+ tracer.AddTraceEvent(ChannelTrace::Severity::Error,
+ grpc_slice_from_static_string("trace four error"));
+ ValidateChannelTrace(&tracer, 4, GetParam());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ ValidateChannelTrace(&tracer, 6, GetParam());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ ValidateChannelTrace(&tracer, 10, GetParam());
}
// Tests more complex functionality, like a parent channel tracking
@@ -141,42 +152,43 @@ TEST_P(ChannelTracerTest, BasicTest) {
// and this function will both hold refs to the subchannel.
TEST_P(ChannelTracerTest, ComplexTest) {
grpc_core::ExecCtx exec_ctx;
- RefCountedPtr<ChannelTrace> tracer = MakeRefCounted<ChannelTrace>(GetParam());
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- RefCountedPtr<ChannelTrace> sc1 = MakeRefCounted<ChannelTrace>(GetParam());
- tracer->AddTraceEventReferencingSubchannel(
+ ChannelTrace tracer(GetParam());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ ChannelFixture channel1(GetParam());
+ RefCountedPtr<ChannelNode> sc1 =
+ MakeRefCounted<ChannelNode>(channel1.channel(), GetParam());
+ tracer.AddTraceEventReferencingSubchannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel one created"), sc1);
- ValidateChannelTrace(tracer, 3, GetParam());
- AddSimpleTrace(sc1);
- AddSimpleTrace(sc1);
- AddSimpleTrace(sc1);
- ValidateChannelTrace(sc1, 3, GetParam());
- AddSimpleTrace(sc1);
- AddSimpleTrace(sc1);
- AddSimpleTrace(sc1);
- ValidateChannelTrace(sc1, 6, GetParam());
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- ValidateChannelTrace(tracer, 5, GetParam());
- ValidateTraceDataMatchedUuidLookup(tracer);
- RefCountedPtr<ChannelTrace> sc2 = MakeRefCounted<ChannelTrace>(GetParam());
- tracer->AddTraceEventReferencingChannel(
+ ValidateChannelTrace(&tracer, 3, GetParam());
+ AddSimpleTrace(sc1->trace());
+ AddSimpleTrace(sc1->trace());
+ AddSimpleTrace(sc1->trace());
+ ValidateChannelTrace(sc1->trace(), 3, GetParam());
+ AddSimpleTrace(sc1->trace());
+ AddSimpleTrace(sc1->trace());
+ AddSimpleTrace(sc1->trace());
+ ValidateChannelTrace(sc1->trace(), 6, GetParam());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ ValidateChannelTrace(&tracer, 5, GetParam());
+ ChannelFixture channel2(GetParam());
+ RefCountedPtr<ChannelNode> sc2 =
+ MakeRefCounted<ChannelNode>(channel2.channel(), GetParam());
+ tracer.AddTraceEventReferencingChannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("LB channel two created"), sc2);
- tracer->AddTraceEventReferencingSubchannel(
+ tracer.AddTraceEventReferencingSubchannel(
ChannelTrace::Severity::Warning,
grpc_slice_from_static_string("subchannel one inactive"), sc1);
- ValidateChannelTrace(tracer, 7, GetParam());
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- ValidateTraceDataMatchedUuidLookup(tracer);
- tracer.reset(nullptr);
+ ValidateChannelTrace(&tracer, 7, GetParam());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
sc1.reset(nullptr);
sc2.reset(nullptr);
}
@@ -186,39 +198,44 @@ TEST_P(ChannelTracerTest, ComplexTest) {
// gets deleted.
TEST_P(ChannelTracerTest, TestNesting) {
grpc_core::ExecCtx exec_ctx;
- RefCountedPtr<ChannelTrace> tracer = MakeRefCounted<ChannelTrace>(GetParam());
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- ValidateChannelTrace(tracer, 2, GetParam());
- RefCountedPtr<ChannelTrace> sc1 = MakeRefCounted<ChannelTrace>(GetParam());
- tracer->AddTraceEventReferencingChannel(
+ ChannelTrace tracer(GetParam());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ ValidateChannelTrace(&tracer, 2, GetParam());
+ ChannelFixture channel1(GetParam());
+ RefCountedPtr<ChannelNode> sc1 =
+ MakeRefCounted<ChannelNode>(channel1.channel(), GetParam());
+ tracer.AddTraceEventReferencingChannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel one created"), sc1);
- ValidateChannelTrace(tracer, 3, GetParam());
- AddSimpleTrace(sc1);
- RefCountedPtr<ChannelTrace> conn1 = MakeRefCounted<ChannelTrace>(GetParam());
+ ValidateChannelTrace(&tracer, 3, GetParam());
+ AddSimpleTrace(sc1->trace());
+ ChannelFixture channel2(GetParam());
+ RefCountedPtr<ChannelNode> conn1 =
+ MakeRefCounted<ChannelNode>(channel2.channel(), GetParam());
// nesting one level deeper.
- sc1->AddTraceEventReferencingSubchannel(
+ sc1->trace()->AddTraceEventReferencingSubchannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("connection one created"), conn1);
- ValidateChannelTrace(tracer, 3, GetParam());
- AddSimpleTrace(conn1);
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- ValidateChannelTrace(tracer, 5, GetParam());
- ValidateChannelTrace(conn1, 1, GetParam());
- RefCountedPtr<ChannelTrace> sc2 = MakeRefCounted<ChannelTrace>(GetParam());
- tracer->AddTraceEventReferencingSubchannel(
+ ValidateChannelTrace(&tracer, 3, GetParam());
+ AddSimpleTrace(conn1->trace());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ ValidateChannelTrace(&tracer, 5, GetParam());
+ ValidateChannelTrace(conn1->trace(), 1, GetParam());
+ ChannelFixture channel3(GetParam());
+ RefCountedPtr<ChannelNode> sc2 =
+ MakeRefCounted<ChannelNode>(channel3.channel(), GetParam());
+ tracer.AddTraceEventReferencingSubchannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel two created"), sc2);
// this trace should not get added to the parents children since it is already
// present in the tracer.
- tracer->AddTraceEventReferencingChannel(
+ tracer.AddTraceEventReferencingChannel(
ChannelTrace::Severity::Warning,
grpc_slice_from_static_string("subchannel one inactive"), sc1);
- AddSimpleTrace(tracer);
- ValidateChannelTrace(tracer, 8, GetParam());
- tracer.reset(nullptr);
+ AddSimpleTrace(&tracer);
+ ValidateChannelTrace(&tracer, 8, GetParam());
sc1.reset(nullptr);
sc2.reset(nullptr);
conn1.reset(nullptr);
@@ -228,6 +245,7 @@ INSTANTIATE_TEST_CASE_P(ChannelTracerTestSweep, ChannelTracerTest,
::testing::Values(0, 1, 2, 6, 10, 15));
} // namespace testing
+} // namespace channelz
} // namespace grpc_core
int main(int argc, char** argv) {
diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc
new file mode 100644
index 0000000000..058eea914c
--- /dev/null
+++ b/test/core/channel/channelz_test.cc
@@ -0,0 +1,216 @@
+/*
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <gtest/gtest.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/channel/channel_trace.h"
+#include "src/core/lib/channel/channelz.h"
+#include "src/core/lib/channel/channelz_registry.h"
+#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/json/json.h"
+#include "src/core/lib/surface/channel.h"
+
+#include "test/core/util/test_config.h"
+#include "test/cpp/util/channel_trace_proto_helper.h"
+
+#include <grpc/support/string_util.h>
+#include <stdlib.h>
+#include <string.h>
+
+namespace grpc_core {
+namespace channelz {
+namespace testing {
+
+// testing peer to access channel internals
+class ChannelNodePeer {
+ public:
+ ChannelNodePeer(ChannelNode* channel) : channel_(channel) {}
+ grpc_millis last_call_started_millis() {
+ return (grpc_millis)gpr_atm_no_barrier_load(
+ &channel_->last_call_started_millis_);
+ }
+
+ private:
+ ChannelNode* channel_;
+};
+
+namespace {
+
+grpc_json* GetJsonChild(grpc_json* parent, const char* key) {
+ EXPECT_NE(parent, nullptr);
+ for (grpc_json* child = parent->child; child != nullptr;
+ child = child->next) {
+ if (child->key != nullptr && strcmp(child->key, key) == 0) return child;
+ }
+ return nullptr;
+}
+
+class ChannelFixture {
+ public:
+ ChannelFixture(int max_trace_nodes) {
+ grpc_arg client_a[2];
+ client_a[0].type = GRPC_ARG_INTEGER;
+ client_a[0].key =
+ const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE);
+ client_a[0].value.integer = max_trace_nodes;
+ client_a[1].type = GRPC_ARG_INTEGER;
+ client_a[1].key = const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ);
+ client_a[1].value.integer = true;
+ grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
+ channel_ =
+ grpc_insecure_channel_create("fake_target", &client_args, nullptr);
+ }
+
+ ~ChannelFixture() { grpc_channel_destroy(channel_); }
+
+ grpc_channel* channel() { return channel_; }
+
+ private:
+ grpc_channel* channel_;
+};
+
+struct validate_channel_data_args {
+ int64_t calls_started;
+ int64_t calls_failed;
+ int64_t calls_succeeded;
+};
+
+void ValidateChildInteger(grpc_json* json, int64_t expect, const char* key) {
+ grpc_json* gotten_json = GetJsonChild(json, key);
+ ASSERT_NE(gotten_json, nullptr);
+ int64_t gotten_number = (int64_t)strtol(gotten_json->value, nullptr, 0);
+ EXPECT_EQ(gotten_number, expect);
+}
+
+void ValidateCounters(char* json_str, validate_channel_data_args args) {
+ grpc_json* json = grpc_json_parse_string(json_str);
+ ASSERT_NE(json, nullptr);
+ grpc_json* data = GetJsonChild(json, "data");
+ ValidateChildInteger(data, args.calls_started, "callsStarted");
+ ValidateChildInteger(data, args.calls_failed, "callsFailed");
+ ValidateChildInteger(data, args.calls_succeeded, "callsSucceeded");
+ grpc_json_destroy(json);
+}
+
+void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) {
+ char* json_str = channel->RenderJSON();
+ grpc::testing::ValidateChannelProtoJsonTranslation(json_str);
+ ValidateCounters(json_str, args);
+ gpr_free(json_str);
+}
+
+grpc_millis GetLastCallStartedMillis(ChannelNode* channel) {
+ ChannelNodePeer peer(channel);
+ return peer.last_call_started_millis();
+}
+
+void ChannelzSleep(int64_t sleep_us) {
+ gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_micros(sleep_us, GPR_TIMESPAN)));
+ grpc_core::ExecCtx::Get()->InvalidateNow();
+}
+
+} // anonymous namespace
+
+class ChannelzChannelTest : public ::testing::TestWithParam<size_t> {};
+
+TEST_P(ChannelzChannelTest, BasicChannel) {
+ grpc_core::ExecCtx exec_ctx;
+ ChannelFixture channel(GetParam());
+ ChannelNode* channelz_channel =
+ grpc_channel_get_channelz_node(channel.channel());
+ char* json_str = channelz_channel->RenderJSON();
+ ValidateCounters(json_str, {0, 0, 0});
+ gpr_free(json_str);
+}
+
+TEST(ChannelzChannelTest, ChannelzDisabled) {
+ grpc_core::ExecCtx exec_ctx;
+ grpc_channel* channel =
+ grpc_insecure_channel_create("fake_target", nullptr, nullptr);
+ ChannelNode* channelz_channel = grpc_channel_get_channelz_node(channel);
+ ASSERT_EQ(channelz_channel, nullptr);
+ grpc_channel_destroy(channel);
+}
+
+TEST_P(ChannelzChannelTest, BasicChannelAPIFunctionality) {
+ grpc_core::ExecCtx exec_ctx;
+ ChannelFixture channel(GetParam());
+ ChannelNode* channelz_channel =
+ grpc_channel_get_channelz_node(channel.channel());
+ channelz_channel->RecordCallStarted();
+ channelz_channel->RecordCallFailed();
+ channelz_channel->RecordCallSucceeded();
+ ValidateChannel(channelz_channel, {1, 1, 1});
+ channelz_channel->RecordCallStarted();
+ channelz_channel->RecordCallFailed();
+ channelz_channel->RecordCallSucceeded();
+ channelz_channel->RecordCallStarted();
+ channelz_channel->RecordCallFailed();
+ channelz_channel->RecordCallSucceeded();
+ ValidateChannel(channelz_channel, {3, 3, 3});
+}
+
+TEST_P(ChannelzChannelTest, LastCallStartedMillis) {
+ grpc_core::ExecCtx exec_ctx;
+ ChannelFixture channel(GetParam());
+ ChannelNode* channelz_channel =
+ grpc_channel_get_channelz_node(channel.channel());
+ // start a call to set the last call started timestamp
+ channelz_channel->RecordCallStarted();
+ grpc_millis millis1 = GetLastCallStartedMillis(channelz_channel);
+ // time gone by should not affect the timestamp
+ ChannelzSleep(100);
+ grpc_millis millis2 = GetLastCallStartedMillis(channelz_channel);
+ EXPECT_EQ(millis1, millis2);
+ // calls succeeded or failed should not affect the timestamp
+ ChannelzSleep(100);
+ channelz_channel->RecordCallFailed();
+ channelz_channel->RecordCallSucceeded();
+ grpc_millis millis3 = GetLastCallStartedMillis(channelz_channel);
+ EXPECT_EQ(millis1, millis3);
+ // another call started should affect the timestamp
+ // sleep for extra long to avoid flakes (since we cache Now())
+ ChannelzSleep(5000);
+ channelz_channel->RecordCallStarted();
+ grpc_millis millis4 = GetLastCallStartedMillis(channelz_channel);
+ EXPECT_NE(millis1, millis4);
+}
+
+INSTANTIATE_TEST_CASE_P(ChannelzChannelTestSweep, ChannelzChannelTest,
+ ::testing::Values(0, 1, 2, 6, 10, 15));
+
+} // namespace testing
+} // namespace channelz
+} // namespace grpc_core
+
+int main(int argc, char** argv) {
+ grpc_test_init(argc, argv);
+ grpc_init();
+ ::testing::InitGoogleTest(&argc, argv);
+ int ret = RUN_ALL_TESTS();
+ grpc_shutdown();
+ return ret;
+}
diff --git a/test/core/end2end/end2end_nosec_tests.cc b/test/core/end2end/end2end_nosec_tests.cc
index a70128254a..c6a4005fb3 100644
--- a/test/core/end2end/end2end_nosec_tests.cc
+++ b/test/core/end2end/end2end_nosec_tests.cc
@@ -54,6 +54,8 @@ extern void cancel_in_a_vacuum(grpc_end2end_test_config config);
extern void cancel_in_a_vacuum_pre_init(void);
extern void cancel_with_status(grpc_end2end_test_config config);
extern void cancel_with_status_pre_init(void);
+extern void channelz(grpc_end2end_test_config config);
+extern void channelz_pre_init(void);
extern void compressed_payload(grpc_end2end_test_config config);
extern void compressed_payload_pre_init(void);
extern void connectivity(grpc_end2end_test_config config);
@@ -86,8 +88,6 @@ extern void keepalive_timeout(grpc_end2end_test_config config);
extern void keepalive_timeout_pre_init(void);
extern void large_metadata(grpc_end2end_test_config config);
extern void large_metadata_pre_init(void);
-extern void load_reporting_hook(grpc_end2end_test_config config);
-extern void load_reporting_hook_pre_init(void);
extern void max_concurrent_streams(grpc_end2end_test_config config);
extern void max_concurrent_streams_pre_init(void);
extern void max_connection_age(grpc_end2end_test_config config);
@@ -201,6 +201,7 @@ void grpc_end2end_tests_pre_init(void) {
cancel_before_invoke_pre_init();
cancel_in_a_vacuum_pre_init();
cancel_with_status_pre_init();
+ channelz_pre_init();
compressed_payload_pre_init();
connectivity_pre_init();
default_host_pre_init();
@@ -217,7 +218,6 @@ void grpc_end2end_tests_pre_init(void) {
invoke_large_request_pre_init();
keepalive_timeout_pre_init();
large_metadata_pre_init();
- load_reporting_hook_pre_init();
max_concurrent_streams_pre_init();
max_connection_age_pre_init();
max_connection_idle_pre_init();
@@ -287,6 +287,7 @@ void grpc_end2end_tests(int argc, char **argv,
cancel_before_invoke(config);
cancel_in_a_vacuum(config);
cancel_with_status(config);
+ channelz(config);
compressed_payload(config);
connectivity(config);
default_host(config);
@@ -303,7 +304,6 @@ void grpc_end2end_tests(int argc, char **argv,
invoke_large_request(config);
keepalive_timeout(config);
large_metadata(config);
- load_reporting_hook(config);
max_concurrent_streams(config);
max_connection_age(config);
max_connection_idle(config);
@@ -404,6 +404,10 @@ void grpc_end2end_tests(int argc, char **argv,
cancel_with_status(config);
continue;
}
+ if (0 == strcmp("channelz", argv[i])) {
+ channelz(config);
+ continue;
+ }
if (0 == strcmp("compressed_payload", argv[i])) {
compressed_payload(config);
continue;
@@ -468,10 +472,6 @@ void grpc_end2end_tests(int argc, char **argv,
large_metadata(config);
continue;
}
- if (0 == strcmp("load_reporting_hook", argv[i])) {
- load_reporting_hook(config);
- continue;
- }
if (0 == strcmp("max_concurrent_streams", argv[i])) {
max_concurrent_streams(config);
continue;
diff --git a/test/core/end2end/end2end_tests.cc b/test/core/end2end/end2end_tests.cc
index bf75dd4579..7748a39cb5 100644
--- a/test/core/end2end/end2end_tests.cc
+++ b/test/core/end2end/end2end_tests.cc
@@ -56,6 +56,8 @@ extern void cancel_in_a_vacuum(grpc_end2end_test_config config);
extern void cancel_in_a_vacuum_pre_init(void);
extern void cancel_with_status(grpc_end2end_test_config config);
extern void cancel_with_status_pre_init(void);
+extern void channelz(grpc_end2end_test_config config);
+extern void channelz_pre_init(void);
extern void compressed_payload(grpc_end2end_test_config config);
extern void compressed_payload_pre_init(void);
extern void connectivity(grpc_end2end_test_config config);
@@ -88,8 +90,6 @@ extern void keepalive_timeout(grpc_end2end_test_config config);
extern void keepalive_timeout_pre_init(void);
extern void large_metadata(grpc_end2end_test_config config);
extern void large_metadata_pre_init(void);
-extern void load_reporting_hook(grpc_end2end_test_config config);
-extern void load_reporting_hook_pre_init(void);
extern void max_concurrent_streams(grpc_end2end_test_config config);
extern void max_concurrent_streams_pre_init(void);
extern void max_connection_age(grpc_end2end_test_config config);
@@ -204,6 +204,7 @@ void grpc_end2end_tests_pre_init(void) {
cancel_before_invoke_pre_init();
cancel_in_a_vacuum_pre_init();
cancel_with_status_pre_init();
+ channelz_pre_init();
compressed_payload_pre_init();
connectivity_pre_init();
default_host_pre_init();
@@ -220,7 +221,6 @@ void grpc_end2end_tests_pre_init(void) {
invoke_large_request_pre_init();
keepalive_timeout_pre_init();
large_metadata_pre_init();
- load_reporting_hook_pre_init();
max_concurrent_streams_pre_init();
max_connection_age_pre_init();
max_connection_idle_pre_init();
@@ -291,6 +291,7 @@ void grpc_end2end_tests(int argc, char **argv,
cancel_before_invoke(config);
cancel_in_a_vacuum(config);
cancel_with_status(config);
+ channelz(config);
compressed_payload(config);
connectivity(config);
default_host(config);
@@ -307,7 +308,6 @@ void grpc_end2end_tests(int argc, char **argv,
invoke_large_request(config);
keepalive_timeout(config);
large_metadata(config);
- load_reporting_hook(config);
max_concurrent_streams(config);
max_connection_age(config);
max_connection_idle(config);
@@ -412,6 +412,10 @@ void grpc_end2end_tests(int argc, char **argv,
cancel_with_status(config);
continue;
}
+ if (0 == strcmp("channelz", argv[i])) {
+ channelz(config);
+ continue;
+ }
if (0 == strcmp("compressed_payload", argv[i])) {
compressed_payload(config);
continue;
@@ -476,10 +480,6 @@ void grpc_end2end_tests(int argc, char **argv,
large_metadata(config);
continue;
}
- if (0 == strcmp("load_reporting_hook", argv[i])) {
- load_reporting_hook(config);
- continue;
- }
if (0 == strcmp("max_concurrent_streams", argv[i])) {
max_concurrent_streams(config);
continue;
diff --git a/test/core/end2end/fixtures/h2_load_reporting.cc b/test/core/end2end/fixtures/h2_load_reporting.cc
deleted file mode 100644
index 18ea10a8d2..0000000000
--- a/test/core/end2end/fixtures/h2_load_reporting.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *
- * 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 <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/sync.h>
-
-#include "src/core/ext/filters/client_channel/client_channel.h"
-#include "src/core/ext/filters/http/server/http_server_filter.h"
-#include "src/core/ext/filters/load_reporting/server_load_reporting_plugin.h"
-#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
-#include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/channel/connected_channel.h"
-#include "src/core/lib/gpr/host_port.h"
-#include "src/core/lib/surface/channel.h"
-#include "src/core/lib/surface/server.h"
-#include "test/core/util/port.h"
-#include "test/core/util/test_config.h"
-
-typedef struct load_reporting_fixture_data {
- char* localaddr;
-} load_reporting_fixture_data;
-
-static grpc_end2end_test_fixture chttp2_create_fixture_load_reporting(
- grpc_channel_args* client_args, grpc_channel_args* server_args) {
- grpc_end2end_test_fixture f;
- int port = grpc_pick_unused_port_or_die();
- load_reporting_fixture_data* ffd = static_cast<load_reporting_fixture_data*>(
- gpr_malloc(sizeof(load_reporting_fixture_data)));
- memset(&f, 0, sizeof(f));
-
- gpr_join_host_port(&ffd->localaddr, "localhost", port);
-
- f.fixture_data = ffd;
- f.cq = grpc_completion_queue_create_for_next(nullptr);
- f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
-
- return f;
-}
-
-void chttp2_init_client_load_reporting(grpc_end2end_test_fixture* f,
- grpc_channel_args* client_args) {
- load_reporting_fixture_data* ffd =
- static_cast<load_reporting_fixture_data*>(f->fixture_data);
- f->client =
- grpc_insecure_channel_create(ffd->localaddr, client_args, nullptr);
- GPR_ASSERT(f->client);
-}
-
-void chttp2_init_server_load_reporting(grpc_end2end_test_fixture* f,
- grpc_channel_args* server_args) {
- load_reporting_fixture_data* ffd =
- static_cast<load_reporting_fixture_data*>(f->fixture_data);
- grpc_arg arg = grpc_load_reporting_enable_arg();
- if (f->server) {
- grpc_server_destroy(f->server);
- }
- server_args = grpc_channel_args_copy_and_add(server_args, &arg, 1);
- f->server = grpc_server_create(server_args, nullptr);
- {
- grpc_core::ExecCtx exec_ctx;
- grpc_channel_args_destroy(server_args);
- }
- grpc_server_register_completion_queue(f->server, f->cq, nullptr);
- GPR_ASSERT(grpc_server_add_insecure_http2_port(f->server, ffd->localaddr));
- grpc_server_start(f->server);
-}
-
-void chttp2_tear_down_load_reporting(grpc_end2end_test_fixture* f) {
- load_reporting_fixture_data* ffd =
- static_cast<load_reporting_fixture_data*>(f->fixture_data);
- gpr_free(ffd->localaddr);
- gpr_free(ffd);
-}
-
-/* All test configurations */
-static grpc_end2end_test_config configs[] = {
- {"chttp2/fullstack+load_reporting",
- FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
- FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
- FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
- nullptr, chttp2_create_fixture_load_reporting,
- chttp2_init_client_load_reporting, chttp2_init_server_load_reporting,
- chttp2_tear_down_load_reporting},
-};
-
-int main(int argc, char** argv) {
- size_t i;
-
- grpc_test_init(argc, argv);
- grpc_end2end_tests_pre_init();
- grpc_init();
-
- for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
- grpc_end2end_tests(argc, argv, configs[i]);
- }
-
- grpc_shutdown();
-
- return 0;
-}
diff --git a/test/core/end2end/fuzzers/api_fuzzer.cc b/test/core/end2end/fuzzers/api_fuzzer.cc
index 6c226818b9..eacfd4a8c3 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.cc
+++ b/test/core/end2end/fuzzers/api_fuzzer.cc
@@ -1046,6 +1046,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
op->reserved = nullptr;
op->flags = grpc_fuzzer_get_next_uint32(&inp);
}
+ if (g_channel == nullptr) ok = false;
if (ok) {
validator* v = make_finished_batch_validator(g_active_call, has_ops);
g_active_call->pending_ops++;
diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py
index 1851214191..d5c23262e3 100755
--- a/test/core/end2end/gen_build_yaml.py
+++ b/test/core/end2end/gen_build_yaml.py
@@ -47,7 +47,9 @@ inproc_fixture_options = default_unsecure_fixture_options._replace(
END2END_FIXTURES = {
'h2_compress': default_unsecure_fixture_options._replace(enables_compression=True),
'h2_census': default_unsecure_fixture_options,
- 'h2_load_reporting': default_unsecure_fixture_options,
+ # This cmake target is disabled for now because it depends on OpenCensus,
+ # which is Bazel-only.
+ # 'h2_load_reporting': default_unsecure_fixture_options,
'h2_fakesec': default_secure_fixture_options._replace(ci_mac=False),
'h2_fd': fd_unsecure_fixture_options,
'h2_full': default_unsecure_fixture_options,
@@ -106,6 +108,7 @@ END2END_TESTS = {
needs_compression=True),
'connectivity': connectivity_test_options._replace(needs_names=True,
proxyable=False, cpu_cost=LOWCPU, exclude_iomgrs=['uv']),
+ 'channelz': default_test_options,
'default_host': default_test_options._replace(
needs_fullstack=True, needs_dns=True, needs_names=True),
'call_host_override': default_test_options._replace(
@@ -142,7 +145,9 @@ END2END_TESTS = {
'no_logging': default_test_options._replace(traceable=False),
'no_op': default_test_options,
'payload': default_test_options,
- 'load_reporting_hook': default_test_options,
+ # This cmake target is disabled for now because it depends on OpenCensus,
+ # which is Bazel-only.
+ # 'load_reporting_hook': default_test_options,
'ping_pong_streaming': default_test_options._replace(cpu_cost=LOWCPU),
'ping': connectivity_test_options._replace(proxyable=False,
cpu_cost=LOWCPU),
diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl
index 706f4fa86d..39b11d08ad 100755
--- a/test/core/end2end/generate_tests.bzl
+++ b/test/core/end2end/generate_tests.bzl
@@ -45,7 +45,9 @@ def fixture_options(fullstack=True, includes_proxy=False, dns_resolver=True,
END2END_FIXTURES = {
'h2_compress': fixture_options(),
'h2_census': fixture_options(),
- 'h2_load_reporting': fixture_options(),
+ # TODO(juanlishen): This is disabled for now, but should be considered to re-enable once we have
+ # decided how the load reporting service should be enabled.
+ #'h2_load_reporting': fixture_options(),
'h2_fakesec': fixture_options(),
'h2_fd': fixture_options(dns_resolver=False, fullstack=False,
client_channel=False,
@@ -113,6 +115,7 @@ END2END_TESTS = {
'compressed_payload': test_options(proxyable=False, exclude_inproc=True),
'connectivity': test_options(needs_fullstack=True, needs_names=True,
proxyable=False),
+ 'channelz': test_options(),
'default_host': test_options(needs_fullstack=True, needs_dns=True,
needs_names=True),
'disappearing_server': test_options(needs_fullstack=True,needs_names=True),
@@ -138,7 +141,10 @@ END2END_TESTS = {
'no_logging': test_options(traceable=False),
'no_op': test_options(),
'payload': test_options(),
- 'load_reporting_hook': test_options(),
+ # TODO(juanlishen): This is disabled for now because it depends on some generated functions in
+ # end2end_tests.cc, which are not generated because they would depend on OpenCensus while
+ # OpenCensus can only be built via Bazel so far.
+ # 'load_reporting_hook': test_options(),
'ping_pong_streaming': test_options(),
'ping': test_options(needs_fullstack=True, proxyable=False),
'proxy_auth': test_options(needs_proxy_auth=True),
diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc
new file mode 100644
index 0000000000..eb052119ca
--- /dev/null
+++ b/test/core/end2end/tests/channelz.cc
@@ -0,0 +1,299 @@
+/*
+ *
+ * Copyright 2015 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 "src/core/lib/surface/channel.h"
+
+#include <grpc/byte_buffer.h>
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include "src/core/lib/gpr/string.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 run_one_request(grpc_end2end_test_config config,
+ grpc_end2end_test_fixture f,
+ bool request_is_success) {
+ 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;
+
+ 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);
+
+ 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->data.recv_status_on_client.error_string = nullptr;
+ 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);
+
+ 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 =
+ request_is_success ? GRPC_STATUS_OK : GRPC_STATUS_UNIMPLEMENTED;
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
+ 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(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == call_details.flags);
+
+ 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_channelz(grpc_end2end_test_config config) {
+ grpc_end2end_test_fixture f;
+
+ grpc_arg client_a;
+ client_a.type = GRPC_ARG_INTEGER;
+ client_a.key = const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ);
+ client_a.value.integer = true;
+ grpc_channel_args client_args = {1, &client_a};
+
+ f = begin_test(config, "test_channelz", &client_args, nullptr);
+ grpc_core::channelz::ChannelNode* channelz_channel =
+ grpc_channel_get_channelz_node(f.client);
+
+ GPR_ASSERT(channelz_channel != nullptr);
+ char* json = channelz_channel->RenderJSON();
+ GPR_ASSERT(json != nullptr);
+ GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"0\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"0\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"0\""));
+ gpr_free(json);
+
+ // one successful request
+ run_one_request(config, f, true);
+
+ json = channelz_channel->RenderJSON();
+ GPR_ASSERT(json != nullptr);
+ GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"1\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"0\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\""));
+ gpr_free(json);
+
+ // one failed request
+ run_one_request(config, f, false);
+
+ json = channelz_channel->RenderJSON();
+ GPR_ASSERT(json != nullptr);
+ gpr_log(GPR_INFO, "%s", json);
+ GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\""));
+ // channel tracing is not enables, so these should not be preset.
+ GPR_ASSERT(nullptr == strstr(json, "\"trace\""));
+ GPR_ASSERT(nullptr == strstr(json, "\"description\":\"Channel created\""));
+ GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\""));
+ gpr_free(json);
+
+ end_test(&f);
+ config.tear_down_data(&f);
+}
+
+static void test_channelz_with_channel_trace(grpc_end2end_test_config config) {
+ grpc_end2end_test_fixture f;
+
+ grpc_arg client_a[2];
+ client_a[0].type = GRPC_ARG_INTEGER;
+ client_a[0].key =
+ const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE);
+ client_a[0].value.integer = 5;
+ client_a[1].type = GRPC_ARG_INTEGER;
+ client_a[1].key = const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ);
+ client_a[1].value.integer = true;
+ grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
+
+ f = begin_test(config, "test_channelz_with_channel_trace", &client_args,
+ nullptr);
+ grpc_core::channelz::ChannelNode* channelz_channel =
+ grpc_channel_get_channelz_node(f.client);
+
+ GPR_ASSERT(channelz_channel != nullptr);
+ char* json = channelz_channel->RenderJSON();
+ GPR_ASSERT(json != nullptr);
+ gpr_log(GPR_INFO, "%s", json);
+ GPR_ASSERT(nullptr != strstr(json, "\"trace\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"description\":\"Channel created\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"severity\":\"CT_INFO\""));
+ gpr_free(json);
+
+ end_test(&f);
+ config.tear_down_data(&f);
+}
+
+static void test_channelz_disabled(grpc_end2end_test_config config) {
+ grpc_end2end_test_fixture f;
+
+ f = begin_test(config, "test_channelz_disabled", nullptr, nullptr);
+ grpc_core::channelz::ChannelNode* channelz_channel =
+ grpc_channel_get_channelz_node(f.client);
+ GPR_ASSERT(channelz_channel == nullptr);
+ // one successful request
+ run_one_request(config, f, true);
+ GPR_ASSERT(channelz_channel == nullptr);
+ end_test(&f);
+ config.tear_down_data(&f);
+}
+
+void channelz(grpc_end2end_test_config config) {
+ test_channelz(config);
+ test_channelz_with_channel_trace(config);
+ test_channelz_disabled(config);
+}
+
+void channelz_pre_init(void) {}
diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD
index bbf0815e6f..cc1b6aee5e 100644
--- a/test/core/iomgr/BUILD
+++ b/test/core/iomgr/BUILD
@@ -18,7 +18,10 @@ licenses(["notice"]) # Apache v2
load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
-grpc_package(name = "test/core/iomgr", visibility = "public") # Useful for third party devs to test their io manager implementation.
+grpc_package(
+ name = "test/core/iomgr",
+ visibility = "public",
+) # Useful for third party devs to test their io manager implementation.
grpc_cc_library(
name = "endpoint_tests",
@@ -73,15 +76,27 @@ grpc_cc_test(
)
grpc_cc_test(
+ name = "ev_epollex_linux_test",
+ srcs = ["ev_epollex_linux_test.cc"],
+ language = "C++",
+ deps = [
+ "//:gpr",
+ "//:grpc",
+ "//test/core/util:gpr_test_util",
+ "//test/core/util:grpc_test_util",
+ ],
+)
+
+grpc_cc_test(
name = "ev_epollsig_linux_test",
srcs = ["ev_epollsig_linux_test.cc"],
+ language = "C++",
deps = [
"//:gpr",
"//:grpc",
"//test/core/util:gpr_test_util",
"//test/core/util:grpc_test_util",
],
- language = "C++",
)
grpc_cc_test(
@@ -221,13 +236,13 @@ grpc_cc_test(
name = "tcp_server_posix_test",
srcs = ["tcp_server_posix_test.cc"],
language = "C++",
+ tags = ["manual"], # TODO(adelez): Remove once this works on Foundry.
deps = [
"//:gpr",
"//:grpc",
"//test/core/util:gpr_test_util",
"//test/core/util:grpc_test_util",
],
- tags = ["manual"], # TODO(adelez): Remove once this works on Foundry.
)
grpc_cc_test(
diff --git a/test/core/iomgr/ev_epollex_linux_test.cc b/test/core/iomgr/ev_epollex_linux_test.cc
new file mode 100644
index 0000000000..08d1e68b39
--- /dev/null
+++ b/test/core/iomgr/ev_epollex_linux_test.cc
@@ -0,0 +1,115 @@
+/*
+ *
+ * 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.
+ *
+ */
+#include "src/core/lib/iomgr/port.h"
+
+/* This test only relevant on linux systems where epoll() is available */
+#if defined(GRPC_LINUX_EPOLL_CREATE1) && defined(GRPC_LINUX_EVENTFD)
+#include "src/core/lib/iomgr/ev_epollex_linux.h"
+
+#include <grpc/grpc.h>
+#include <string.h>
+#include <sys/eventfd.h>
+
+#include "test/core/util/test_config.h"
+
+static void pollset_destroy(void* ps, grpc_error* error) {
+ grpc_pollset_destroy(static_cast<grpc_pollset*>(ps));
+ gpr_free(ps);
+}
+
+// This test is added to cover the case found in bug:
+// https://github.com/grpc/grpc/issues/15760
+static void test_pollable_owner_fd() {
+ grpc_core::ExecCtx exec_ctx;
+ int ev_fd1;
+ int ev_fd2;
+ grpc_fd* grpc_fd1;
+ grpc_fd* grpc_fd2;
+ grpc_pollset* ps;
+ gpr_mu* mu;
+
+ // == Create two grpc_fds ==
+ // All we need is two file descriptors. Doesn't matter what type. We use
+ // eventfd type here for the purpose of this test
+ ev_fd1 = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
+ ev_fd2 = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
+ if (ev_fd1 < 0 || ev_fd2 < 0) {
+ gpr_log(GPR_ERROR, "Error in creating event fds for the test");
+ return;
+ }
+ grpc_fd1 = grpc_fd_create(ev_fd1, "epollex-test-fd1", false);
+ grpc_fd2 = grpc_fd_create(ev_fd2, "epollex-test-fd2", false);
+ grpc_core::ExecCtx::Get()->Flush();
+
+ // == Create a pollset ==
+ ps = static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
+ grpc_pollset_init(ps, &mu);
+ grpc_core::ExecCtx::Get()->Flush();
+
+ // == Add fd1 to pollset ==
+ grpc_pollset_add_fd(ps, grpc_fd1);
+ grpc_core::ExecCtx::Get()->Flush();
+
+ // == Destroy fd1 ==
+ grpc_fd_orphan(grpc_fd1, nullptr, nullptr, "test fd1 orphan");
+ grpc_core::ExecCtx::Get()->Flush();
+
+ // = Add fd2 to pollset ==
+ //
+ // Before https://github.com/grpc/grpc/issues/15760, the following line caused
+ // unexpected behavior (The previous grpc_pollset_add_fd(ps, grpc_fd1) created
+ // an underlying structure in epollex that held a reference to grpc_fd1 which
+ // was being accessed here even after grpc_fd_orphan(grpc_fd1) was called
+ grpc_pollset_add_fd(ps, grpc_fd2);
+ grpc_core::ExecCtx::Get()->Flush();
+
+ // == Destroy fd2 ==
+ grpc_fd_orphan(grpc_fd2, nullptr, nullptr, "test fd2 orphan");
+ grpc_core::ExecCtx::Get()->Flush();
+
+ // == Destroy pollset
+ grpc_closure ps_destroy_closure;
+ GRPC_CLOSURE_INIT(&ps_destroy_closure, pollset_destroy, ps,
+ grpc_schedule_on_exec_ctx);
+ grpc_pollset_shutdown(ps, &ps_destroy_closure);
+ grpc_core::ExecCtx::Get()->Flush();
+}
+
+int main(int argc, char** argv) {
+ const char* poll_strategy = nullptr;
+ grpc_test_init(argc, argv);
+ grpc_init();
+ {
+ grpc_core::ExecCtx exec_ctx;
+ poll_strategy = grpc_get_poll_strategy_name();
+ if (poll_strategy != nullptr && strcmp(poll_strategy, "epollex") == 0) {
+ test_pollable_owner_fd();
+ } else {
+ gpr_log(GPR_INFO,
+ "Skipping the test. The test is only relevant for 'epollex' "
+ "strategy. and the current strategy is: '%s'",
+ poll_strategy);
+ }
+ }
+
+ grpc_shutdown();
+ return 0;
+}
+#else /* defined(GRPC_LINUX_EPOLL_CREATE1) && defined(GRPC_LINUX_EVENTFD) */
+int main(int argc, char** argv) { return 0; }
+#endif
diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c
index 2883810eaa..b09c339cd0 100644
--- a/test/core/surface/public_headers_must_be_c89.c
+++ b/test/core/surface/public_headers_must_be_c89.c
@@ -107,8 +107,6 @@ int main(int argc, char **argv) {
printf("%lx", (unsigned long) grpc_insecure_channel_create);
printf("%lx", (unsigned long) grpc_lame_client_channel_create);
printf("%lx", (unsigned long) grpc_channel_destroy);
- printf("%lx", (unsigned long) grpc_channel_get_trace);
- printf("%lx", (unsigned long) grpc_channel_get_uuid);
printf("%lx", (unsigned long) grpc_call_cancel);
printf("%lx", (unsigned long) grpc_call_cancel_with_status);
printf("%lx", (unsigned long) grpc_call_ref);
diff --git a/test/cpp/microbenchmarks/BUILD b/test/cpp/microbenchmarks/BUILD
index 7b27aed4c3..0c3b9ef816 100644
--- a/test/cpp/microbenchmarks/BUILD
+++ b/test/cpp/microbenchmarks/BUILD
@@ -55,6 +55,20 @@ grpc_cc_binary(
)
grpc_cc_binary(
+ name = "bm_arena",
+ testonly = 1,
+ srcs = ["bm_arena.cc"],
+ deps = [":helpers"],
+)
+
+grpc_cc_binary(
+ name = "bm_channel",
+ testonly = 1,
+ srcs = ["bm_channel.cc"],
+ deps = [":helpers"],
+)
+
+grpc_cc_binary(
name = "bm_cq",
testonly = 1,
srcs = ["bm_cq.cc"],
diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc
index dd1610dc3d..9516b2e3e2 100644
--- a/test/cpp/microbenchmarks/bm_call_create.cc
+++ b/test/cpp/microbenchmarks/bm_call_create.cc
@@ -604,10 +604,13 @@ BENCHMARK_TEMPLATE(BM_IsolatedFilter, HttpServerFilter, SendEmptyMetadata);
typedef Fixture<&grpc_message_size_filter, CHECKS_NOT_LAST> MessageSizeFilter;
BENCHMARK_TEMPLATE(BM_IsolatedFilter, MessageSizeFilter, NoOp);
BENCHMARK_TEMPLATE(BM_IsolatedFilter, MessageSizeFilter, SendEmptyMetadata);
-typedef Fixture<&grpc_server_load_reporting_filter, CHECKS_NOT_LAST>
- LoadReportingFilter;
-BENCHMARK_TEMPLATE(BM_IsolatedFilter, LoadReportingFilter, NoOp);
-BENCHMARK_TEMPLATE(BM_IsolatedFilter, LoadReportingFilter, SendEmptyMetadata);
+// This cmake target is disabled for now because it depends on OpenCensus, which
+// is Bazel-only.
+// typedef Fixture<&grpc_server_load_reporting_filter, CHECKS_NOT_LAST>
+// LoadReportingFilter;
+// BENCHMARK_TEMPLATE(BM_IsolatedFilter, LoadReportingFilter, NoOp);
+// BENCHMARK_TEMPLATE(BM_IsolatedFilter, LoadReportingFilter,
+// SendEmptyMetadata);
////////////////////////////////////////////////////////////////////////////////
// Benchmarks isolating grpc_call
diff --git a/test/cpp/microbenchmarks/bm_channel.cc b/test/cpp/microbenchmarks/bm_channel.cc
new file mode 100644
index 0000000000..15ac997540
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_channel.cc
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Benchmark channel */
+
+#include <benchmark/benchmark.h>
+#include <grpc/grpc.h>
+#include "test/cpp/microbenchmarks/helpers.h"
+#include "test/cpp/util/test_config.h"
+
+auto& force_library_initialization = Library::get();
+
+class ChannelDestroyerFixture {
+ public:
+ ChannelDestroyerFixture() {}
+ virtual ~ChannelDestroyerFixture() {
+ if (channel_) {
+ grpc_channel_destroy(channel_);
+ }
+ }
+ virtual void Init() = 0;
+
+ protected:
+ grpc_channel* channel_ = nullptr;
+};
+
+class InsecureChannelFixture : public ChannelDestroyerFixture {
+ public:
+ InsecureChannelFixture() {}
+ void Init() override {
+ channel_ = grpc_insecure_channel_create("localhost:1234", nullptr, nullptr);
+ }
+};
+
+class LameChannelFixture : public ChannelDestroyerFixture {
+ public:
+ LameChannelFixture() {}
+ void Init() override {
+ channel_ = grpc_lame_client_channel_create(
+ "localhost:1234", GRPC_STATUS_UNAUTHENTICATED, "blah");
+ }
+};
+
+template <class Fixture>
+static void BM_InsecureChannelCreateDestroy(benchmark::State& state) {
+ // In order to test if channel creation time is affected by the number of
+ // already existing channels, we create some initial channels here.
+ Fixture initial_channels[512];
+ for (int i = 0; i < state.range(0); i++) {
+ initial_channels[i].Init();
+ }
+ while (state.KeepRunning()) {
+ Fixture channel;
+ channel.Init();
+ }
+}
+BENCHMARK_TEMPLATE(BM_InsecureChannelCreateDestroy, InsecureChannelFixture)
+ ->Range(0, 512);
+;
+BENCHMARK_TEMPLATE(BM_InsecureChannelCreateDestroy, LameChannelFixture)
+ ->Range(0, 512);
+;
+
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+} // namespace benchmark
+
+int main(int argc, char** argv) {
+ ::benchmark::Initialize(&argc, argv);
+ ::grpc::testing::InitTest(&argc, &argv, false);
+ benchmark::RunTheBenchmarksNamespaced();
+ return 0;
+}
diff --git a/test/cpp/naming/cancel_ares_query_test.cc b/test/cpp/naming/cancel_ares_query_test.cc
index 11cdc0b774..0d59bf6fb6 100644
--- a/test/cpp/naming/cancel_ares_query_test.cc
+++ b/test/cpp/naming/cancel_ares_query_test.cc
@@ -160,10 +160,7 @@ void CheckResolverResultAssertFailureLocked(void* arg, grpc_error* error) {
gpr_mu_unlock(args->mu);
}
-TEST(CancelDuringAresQuery, TestCancelActiveDNSQuery) {
- grpc_core::ExecCtx exec_ctx;
- ArgsStruct args;
- ArgsInit(&args);
+void TestCancelActiveDNSQuery(ArgsStruct* args) {
int fake_dns_port = grpc_pick_unused_port_or_die();
FakeNonResponsiveDNSServer fake_dns_server(fake_dns_port);
char* client_target;
@@ -173,20 +170,47 @@ TEST(CancelDuringAresQuery, TestCancelActiveDNSQuery) {
fake_dns_port));
// create resolver and resolve
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
- grpc_core::ResolverRegistry::CreateResolver(client_target, nullptr,
- args.pollset_set, args.lock);
+ grpc_core::ResolverRegistry::CreateResolver(
+ client_target, nullptr, args->pollset_set, args->lock);
gpr_free(client_target);
grpc_closure on_resolver_result_changed;
GRPC_CLOSURE_INIT(&on_resolver_result_changed,
- CheckResolverResultAssertFailureLocked, (void*)&args,
- grpc_combiner_scheduler(args.lock));
- resolver->NextLocked(&args.channel_args, &on_resolver_result_changed);
+ CheckResolverResultAssertFailureLocked, (void*)args,
+ grpc_combiner_scheduler(args->lock));
+ resolver->NextLocked(&args->channel_args, &on_resolver_result_changed);
// Without resetting and causing resolver shutdown, the
// PollPollsetUntilRequestDone call should never finish.
resolver.reset();
grpc_core::ExecCtx::Get()->Flush();
- PollPollsetUntilRequestDone(&args);
- ArgsFinish(&args);
+ PollPollsetUntilRequestDone(args);
+ ArgsFinish(args);
+}
+
+TEST(CancelDuringAresQuery, TestCancelActiveDNSQuery) {
+ grpc_core::ExecCtx exec_ctx;
+ ArgsStruct args;
+ ArgsInit(&args);
+ TestCancelActiveDNSQuery(&args);
+}
+
+TEST(CancelDuringAresQuery, TestFdsAreDeletedFromPollsetSet) {
+ grpc_core::ExecCtx exec_ctx;
+ ArgsStruct args;
+ ArgsInit(&args);
+ // Add fake_other_pollset_set into the mix to test
+ // that we're explicitly deleting fd's from their pollset.
+ // If we aren't doing so, then the remaining presence of
+ // "fake_other_pollset_set" after the request is done and the resolver
+ // pollset set is destroyed should keep the resolver's fd alive and
+ // fail the test.
+ grpc_pollset_set* fake_other_pollset_set = grpc_pollset_set_create();
+ grpc_pollset_set_add_pollset_set(fake_other_pollset_set, args.pollset_set);
+ // Note that running the cancellation c-ares test is somewhat irrelevant for
+ // this test. This test only cares about what happens to fd's that c-ares
+ // opens.
+ TestCancelActiveDNSQuery(&args);
+ EXPECT_EQ(grpc_iomgr_count_objects_for_testing(), 0u);
+ grpc_pollset_set_destroy(fake_other_pollset_set);
}
TEST(CancelDuringAresQuery,
diff --git a/test/cpp/server/load_reporter/BUILD b/test/cpp/server/load_reporter/BUILD
index 5cb3a00f82..ebfcfbb348 100644
--- a/test/cpp/server/load_reporter/BUILD
+++ b/test/cpp/server/load_reporter/BUILD
@@ -14,7 +14,7 @@
licenses(["notice"]) # Apache v2
-load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_cc_library", "grpc_cc_binary", "grpc_package")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package")
grpc_package(name = "test/cpp/server/load_reporter")
@@ -29,3 +29,35 @@ grpc_cc_test(
"//test/core/util:grpc_test_util",
],
)
+
+grpc_cc_test(
+ name = "lb_load_reporter_test",
+ srcs = ["load_reporter_test.cc"],
+ external_deps = [
+ "gtest",
+ "gmock",
+ "opencensus-stats-test",
+ ],
+ deps = [
+ "//:gpr",
+ "//:grpc",
+ "//:lb_load_reporter",
+ "//test/core/util:gpr_test_util",
+ "//test/core/util:grpc_test_util",
+ ],
+)
+
+grpc_cc_test(
+ name = "lb_get_cpu_stats_test",
+ srcs = ["get_cpu_stats_test.cc"],
+ external_deps = [
+ "gtest",
+ ],
+ deps = [
+ "//:gpr",
+ "//:grpc",
+ "//:lb_get_cpu_stats",
+ "//test/core/util:gpr_test_util",
+ "//test/core/util:grpc_test_util",
+ ],
+)
diff --git a/test/cpp/server/load_reporter/get_cpu_stats_test.cc b/test/cpp/server/load_reporter/get_cpu_stats_test.cc
new file mode 100644
index 0000000000..5b1d5fa3a4
--- /dev/null
+++ b/test/cpp/server/load_reporter/get_cpu_stats_test.cc
@@ -0,0 +1,61 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/impl/codegen/port_platform.h>
+
+#include <grpc/grpc.h>
+#include <gtest/gtest.h>
+
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+
+#include "src/cpp/server/load_reporter/get_cpu_stats.h"
+
+namespace grpc {
+namespace testing {
+namespace {
+
+TEST(GetCpuStatsTest, ReadOnce) { ::grpc::load_reporter::GetCpuStatsImpl(); }
+
+TEST(GetCpuStatsTest, BusyNoLargerThanTotal) {
+ auto p = ::grpc::load_reporter::GetCpuStatsImpl();
+ uint64_t busy = p.first;
+ uint64_t total = p.second;
+ ASSERT_LE(busy, total);
+}
+
+TEST(GetCpuStatsTest, Ascending) {
+ const size_t kRuns = 100;
+ auto prev = ::grpc::load_reporter::GetCpuStatsImpl();
+ for (size_t i = 0; i < kRuns; ++i) {
+ auto cur = ::grpc::load_reporter::GetCpuStatsImpl();
+ ASSERT_LE(prev.first, cur.first);
+ ASSERT_LE(prev.second, cur.second);
+ prev = cur;
+ }
+}
+
+} // namespace
+} // namespace testing
+} // namespace grpc
+
+int main(int argc, char** argv) {
+ grpc_test_init(argc, argv);
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/server/load_reporter/load_data_store_test.cc b/test/cpp/server/load_reporter/load_data_store_test.cc
index aa37b7d6ba..c92c407e4f 100644
--- a/test/cpp/server/load_reporter/load_data_store_test.cc
+++ b/test/cpp/server/load_reporter/load_data_store_test.cc
@@ -393,9 +393,9 @@ TEST_F(PerBalancerStoreTest, Suspend) {
TEST_F(PerBalancerStoreTest, DataAggregation) {
PerBalancerStore per_balancer_store(kLbId1, kLoadKey1);
// Construct some Values.
- LoadRecordValue v1(992, 34, 13, 234.0, 164.0, 173467.38);
+ LoadRecordValue v1(992, 34, 13, 234, 164, 173467);
v1.InsertCallMetric(kMetric1, CallMetricValue(3, 2773.2));
- LoadRecordValue v2(4842, 213, 9, 393.0, 974.0, 1345.2398);
+ LoadRecordValue v2(4842, 213, 9, 393, 974, 1345);
v2.InsertCallMetric(kMetric1, CallMetricValue(7, 25.234));
v2.InsertCallMetric(kMetric2, CallMetricValue(2, 387.08));
// v3 doesn't change the number of in-progress RPCs.
diff --git a/test/cpp/server/load_reporter/load_reporter_test.cc b/test/cpp/server/load_reporter/load_reporter_test.cc
new file mode 100644
index 0000000000..3264dba134
--- /dev/null
+++ b/test/cpp/server/load_reporter/load_reporter_test.cc
@@ -0,0 +1,498 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/impl/codegen/port_platform.h>
+
+#include <set>
+#include <vector>
+
+#include <gmock/gmock.h>
+#include <grpc/grpc.h>
+#include <gtest/gtest.h>
+
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/cpp/server/load_reporter/constants.h"
+#include "src/cpp/server/load_reporter/load_reporter.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+
+#include "opencensus/stats/testing/test_utils.h"
+
+namespace grpc {
+namespace testing {
+namespace {
+
+using ::grpc::lb::v1::LoadBalancingFeedback;
+using ::grpc::load_reporter::CensusViewProvider;
+using ::grpc::load_reporter::CpuStatsProvider;
+using ::grpc::load_reporter::LoadReporter;
+using ::opencensus::stats::View;
+using ::opencensus::stats::ViewData;
+using ::opencensus::stats::ViewDataImpl;
+using ::opencensus::stats::ViewDescriptor;
+using ::testing::DoubleNear;
+using ::testing::Return;
+
+constexpr uint64_t kFeedbackSampleWindowSeconds = 5;
+constexpr uint64_t kFetchAndSampleIntervalSeconds = 1;
+constexpr uint64_t kNumFeedbackSamplesInWindow =
+ kFeedbackSampleWindowSeconds / kFetchAndSampleIntervalSeconds;
+
+class MockCensusViewProvider : public CensusViewProvider {
+ public:
+ MOCK_METHOD0(FetchViewData, CensusViewProvider::ViewDataMap());
+
+ const ::opencensus::stats::ViewDescriptor& FindViewDescriptor(
+ const grpc::string& view_name) {
+ auto it = view_descriptor_map().find(view_name);
+ GPR_ASSERT(it != view_descriptor_map().end());
+ return it->second;
+ }
+};
+
+class MockCpuStatsProvider : public CpuStatsProvider {
+ public:
+ MOCK_METHOD0(GetCpuStats, CpuStatsProvider::CpuStatsSample());
+};
+
+class LoadReporterTest : public ::testing::Test {
+ public:
+ LoadReporterTest() {}
+
+ MockCensusViewProvider* mock_census_view_provider() {
+ return static_cast<MockCensusViewProvider*>(
+ load_reporter_->census_view_provider());
+ }
+
+ void PrepareCpuExpectation(size_t call_num) {
+ auto mock_cpu_stats_provider = static_cast<MockCpuStatsProvider*>(
+ load_reporter_->cpu_stats_provider());
+ ::testing::InSequence s;
+ for (size_t i = 0; i < call_num; ++i) {
+ EXPECT_CALL(*mock_cpu_stats_provider, GetCpuStats())
+ .WillOnce(Return(kCpuStatsSamples[i]))
+ .RetiresOnSaturation();
+ }
+ }
+
+ CpuStatsProvider::CpuStatsSample initial_cpu_stats_{2, 20};
+ const std::vector<CpuStatsProvider::CpuStatsSample> kCpuStatsSamples = {
+ {13, 53}, {64, 96}, {245, 345}, {314, 785},
+ {874, 1230}, {1236, 2145}, {1864, 2974}};
+
+ std::unique_ptr<LoadReporter> load_reporter_;
+
+ const grpc::string kHostname1 = "kHostname1";
+ const grpc::string kHostname2 = "kHostname2";
+ const grpc::string kHostname3 = "kHostname3";
+ // Pad to the length of a valid LB ID.
+ const grpc::string kLbId1 = "kLbId111";
+ const grpc::string kLbId2 = "kLbId222";
+ const grpc::string kLbId3 = "kLbId333";
+ const grpc::string kLbId4 = "kLbId444";
+ const grpc::string kLoadKey1 = "kLoadKey1";
+ const grpc::string kLoadKey2 = "kLoadKey2";
+ const grpc::string kLoadKey3 = "kLoadKey3";
+ const grpc::string kLbTag1 = "kLbTag1";
+ const grpc::string kLbTag2 = "kLbTag2";
+ const grpc::string kLbToken1 = "kLbId111kLbTag1";
+ const grpc::string kLbToken2 = "kLbId222kLbTag2";
+ const grpc::string kUser1 = "kUser1";
+ const grpc::string kUser2 = "kUser2";
+ const grpc::string kUser3 = "kUser3";
+ const grpc::string kClientIp0 = "00";
+ const grpc::string kClientIp1 = "0800000001";
+ const grpc::string kClientIp2 = "3200000000000000000000000000000002";
+ const grpc::string kMetric1 = "kMetric1";
+ const grpc::string kMetric2 = "kMetric2";
+
+ private:
+ void SetUp() override {
+ auto mock_cpu = new MockCpuStatsProvider();
+ auto mock_census = new MockCensusViewProvider();
+ // Prepare the initial CPU stats data. Note that the expectation should be
+ // set up before the load reporter is initialized, because CPU stats is
+ // sampled at that point.
+ EXPECT_CALL(*mock_cpu, GetCpuStats())
+ .WillOnce(Return(initial_cpu_stats_))
+ .RetiresOnSaturation();
+ load_reporter_ = std::unique_ptr<LoadReporter>(
+ new LoadReporter(kFeedbackSampleWindowSeconds,
+ std::unique_ptr<CensusViewProvider>(mock_census),
+ std::unique_ptr<CpuStatsProvider>(mock_cpu)));
+ }
+};
+
+class LbFeedbackTest : public LoadReporterTest {
+ public:
+ // Note that [start, start + count) of the fake samples (maybe plus the
+ // initial record) are in the window now.
+ void VerifyLbFeedback(const LoadBalancingFeedback& lb_feedback, size_t start,
+ size_t count) {
+ const CpuStatsProvider::CpuStatsSample* base =
+ start == 0 ? &initial_cpu_stats_ : &kCpuStatsSamples[start - 1];
+ double expected_cpu_util =
+ static_cast<double>(kCpuStatsSamples[start + count - 1].first -
+ base->first) /
+ static_cast<double>(kCpuStatsSamples[start + count - 1].second -
+ base->second);
+ ASSERT_THAT(static_cast<double>(lb_feedback.server_utilization()),
+ DoubleNear(expected_cpu_util, 0.00001));
+ double qps_sum = 0, eps_sum = 0;
+ for (size_t i = 0; i < count; ++i) {
+ qps_sum += kQpsEpsSamples[start + i].first;
+ eps_sum += kQpsEpsSamples[start + i].second;
+ }
+ double expected_qps = qps_sum / count;
+ double expected_eps = eps_sum / count;
+ // TODO(juanlishen): The error is big because we use sleep(). It should be
+ // much smaller when we use fake clock.
+ ASSERT_THAT(static_cast<double>(lb_feedback.calls_per_second()),
+ DoubleNear(expected_qps, expected_qps / 50));
+ ASSERT_THAT(static_cast<double>(lb_feedback.errors_per_second()),
+ DoubleNear(expected_eps, expected_eps / 50));
+ gpr_log(GPR_INFO,
+ "Verified LB feedback matches the samples of index [%lu, %lu).",
+ start, start + count);
+ }
+
+ const std::vector<std::pair<double, double>> kQpsEpsSamples = {
+ {546.1, 153.1}, {62.1, 54.1}, {578.1, 154.2}, {978.1, 645.1},
+ {1132.1, 846.4}, {531.5, 315.4}, {874.1, 324.9}};
+};
+
+TEST_F(LbFeedbackTest, ZeroDuration) {
+ PrepareCpuExpectation(kCpuStatsSamples.size());
+ EXPECT_CALL(*mock_census_view_provider(), FetchViewData())
+ .WillRepeatedly(
+ Return(::grpc::load_reporter::CensusViewProvider::ViewDataMap()));
+ // Verify that divide-by-zero exception doesn't happen.
+ for (size_t i = 0; i < kCpuStatsSamples.size(); ++i) {
+ load_reporter_->FetchAndSample();
+ }
+ load_reporter_->GenerateLoadBalancingFeedback();
+}
+
+TEST_F(LbFeedbackTest, Normal) {
+ // Prepare view data list using the <QPS, EPS> samples.
+ std::vector<CensusViewProvider::ViewDataMap> view_data_map_list;
+ for (const auto& p : LbFeedbackTest::kQpsEpsSamples) {
+ double qps = p.first;
+ double eps = p.second;
+ double ok_count = (qps - eps) * kFetchAndSampleIntervalSeconds;
+ double error_count = eps * kFetchAndSampleIntervalSeconds;
+ double ok_count_1 = ok_count / 3.0;
+ double ok_count_2 = ok_count - ok_count_1;
+ auto end_count_vd = ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewEndCount),
+ {{{kClientIp0 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusOk},
+ ok_count_1},
+ {{kClientIp0 + kLbToken1, kHostname1, kUser2,
+ ::grpc::load_reporter::kCallStatusOk},
+ ok_count_2},
+ {{kClientIp0 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusClientError},
+ error_count}});
+ // Values for other view data don't matter.
+ auto end_bytes_sent_vd =
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewEndBytesSent),
+ {{{kClientIp0 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusOk},
+ 0},
+ {{kClientIp0 + kLbToken1, kHostname1, kUser2,
+ ::grpc::load_reporter::kCallStatusOk},
+ 0},
+ {{kClientIp0 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusClientError},
+ 0}});
+ auto end_bytes_received_vd =
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewEndBytesReceived),
+ {{{kClientIp0 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusOk},
+ 0},
+ {{kClientIp0 + kLbToken1, kHostname1, kUser2,
+ ::grpc::load_reporter::kCallStatusOk},
+ 0},
+ {{kClientIp0 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusClientError},
+ 0}});
+ auto end_latency_vd = ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewEndLatencyMs),
+ {{{kClientIp0 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusOk},
+ 0},
+ {{kClientIp0 + kLbToken1, kHostname1, kUser2,
+ ::grpc::load_reporter::kCallStatusOk},
+ 0},
+ {{kClientIp0 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusClientError},
+ 0}});
+ view_data_map_list.push_back(
+ {{::grpc::load_reporter::kViewEndCount, end_count_vd},
+ {::grpc::load_reporter::kViewEndBytesSent, end_bytes_sent_vd},
+ {::grpc::load_reporter::kViewEndBytesReceived, end_bytes_received_vd},
+ {::grpc::load_reporter::kViewEndLatencyMs, end_latency_vd}});
+ }
+ {
+ ::testing::InSequence s;
+ for (size_t i = 0; i < view_data_map_list.size(); ++i) {
+ EXPECT_CALL(*mock_census_view_provider(), FetchViewData())
+ .WillOnce(Return(view_data_map_list[i]))
+ .RetiresOnSaturation();
+ }
+ }
+ PrepareCpuExpectation(kNumFeedbackSamplesInWindow + 2);
+ // When the load reporter is created, a trivial LB feedback record is added.
+ // But that's not enough for generating an LB feedback.
+ // Fetch some view data so that non-trivial LB feedback can be generated.
+ for (size_t i = 0; i < kNumFeedbackSamplesInWindow / 2; ++i) {
+ // TODO(juanlishen): Find some fake clock to speed up testing.
+ sleep(1);
+ load_reporter_->FetchAndSample();
+ }
+ VerifyLbFeedback(load_reporter_->GenerateLoadBalancingFeedback(), 0,
+ kNumFeedbackSamplesInWindow / 2);
+ // Fetch more view data so that the feedback record window is just full (the
+ // initial record just falls out of the window).
+ for (size_t i = 0; i < (kNumFeedbackSamplesInWindow + 1) / 2; ++i) {
+ sleep(1);
+ load_reporter_->FetchAndSample();
+ }
+ VerifyLbFeedback(load_reporter_->GenerateLoadBalancingFeedback(), 0,
+ kNumFeedbackSamplesInWindow);
+ // Further fetching will cause the old records to fall out of the window.
+ for (size_t i = 0; i < 2; ++i) {
+ sleep(1);
+ load_reporter_->FetchAndSample();
+ }
+ VerifyLbFeedback(load_reporter_->GenerateLoadBalancingFeedback(), 2,
+ kNumFeedbackSamplesInWindow);
+}
+
+using LoadReportTest = LoadReporterTest;
+
+TEST_F(LoadReportTest, BasicReport) {
+ // Make up the first view data map.
+ CensusViewProvider::ViewDataMap vdm1;
+ vdm1.emplace(
+ ::grpc::load_reporter::kViewStartCount,
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewStartCount),
+ {{{kClientIp1 + kLbToken1, kHostname1, kUser1}, 1234},
+ {{kClientIp2 + kLbToken1, kHostname1, kUser1}, 1225},
+ {{kClientIp0 + kLbToken1, kHostname1, kUser1}, 10},
+ {{kClientIp2 + kLbToken1, kHostname1, kUser2}, 464},
+ {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3}, 101},
+ {{kClientIp1 + kLbToken2, kHostname2, kUser3}, 17},
+ {{kClientIp2 + kLbId3 + kLbTag2, kHostname2, kUser3}, 23}}));
+ vdm1.emplace(::grpc::load_reporter::kViewEndCount,
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewEndCount),
+ {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusOk},
+ 641},
+ {{kClientIp2 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusClientError},
+ 272},
+ {{kClientIp2 + kLbToken1, kHostname1, kUser2,
+ ::grpc::load_reporter::kCallStatusOk},
+ 996},
+ {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3,
+ ::grpc::load_reporter::kCallStatusClientError},
+ 34},
+ {{kClientIp1 + kLbToken2, kHostname2, kUser2,
+ ::grpc::load_reporter::kCallStatusOk},
+ 18}}));
+ vdm1.emplace(::grpc::load_reporter::kViewEndBytesSent,
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewEndBytesSent),
+ {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusOk},
+ 8977},
+ {{kClientIp2 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusClientError},
+ 266},
+ {{kClientIp2 + kLbToken1, kHostname1, kUser2,
+ ::grpc::load_reporter::kCallStatusOk},
+ 1276},
+ {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3,
+ ::grpc::load_reporter::kCallStatusClientError},
+ 77823},
+ {{kClientIp1 + kLbToken2, kHostname2, kUser2,
+ ::grpc::load_reporter::kCallStatusOk},
+ 48}}));
+ vdm1.emplace(::grpc::load_reporter::kViewEndBytesReceived,
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewEndBytesReceived),
+ {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusOk},
+ 2341},
+ {{kClientIp2 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusClientError},
+ 466},
+ {{kClientIp2 + kLbToken1, kHostname1, kUser2,
+ ::grpc::load_reporter::kCallStatusOk},
+ 518},
+ {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3,
+ ::grpc::load_reporter::kCallStatusClientError},
+ 81},
+ {{kClientIp1 + kLbToken2, kHostname2, kUser2,
+ ::grpc::load_reporter::kCallStatusOk},
+ 27}}));
+ vdm1.emplace(::grpc::load_reporter::kViewEndLatencyMs,
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewEndLatencyMs),
+ {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusOk},
+ 3.14},
+ {{kClientIp2 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusClientError},
+ 5.26},
+ {{kClientIp2 + kLbToken1, kHostname1, kUser2,
+ ::grpc::load_reporter::kCallStatusOk},
+ 45.4},
+ {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3,
+ ::grpc::load_reporter::kCallStatusClientError},
+ 4.4},
+ {{kClientIp1 + kLbToken2, kHostname2, kUser2,
+ ::grpc::load_reporter::kCallStatusOk},
+ 2348.0}}));
+ vdm1.emplace(
+ ::grpc::load_reporter::kViewOtherCallMetricCount,
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewOtherCallMetricCount),
+ {{{kClientIp1 + kLbToken1, kHostname1, kUser2, kMetric1}, 1},
+ {{kClientIp1 + kLbToken1, kHostname1, kUser2, kMetric1}, 1},
+ {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric2},
+ 1}}));
+ vdm1.emplace(
+ ::grpc::load_reporter::kViewOtherCallMetricValue,
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewOtherCallMetricValue),
+ {{{kClientIp1 + kLbToken1, kHostname1, kUser2, kMetric1}, 1.2},
+ {{kClientIp1 + kLbToken1, kHostname1, kUser2, kMetric1}, 1.2},
+ {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric2},
+ 3.2}}));
+ // Make up the second view data map.
+ CensusViewProvider::ViewDataMap vdm2;
+ vdm2.emplace(
+ ::grpc::load_reporter::kViewStartCount,
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewStartCount),
+ {{{kClientIp2 + kLbToken1, kHostname1, kUser1}, 3},
+ {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3}, 778}}));
+ vdm2.emplace(::grpc::load_reporter::kViewEndCount,
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewEndCount),
+ {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusOk},
+ 24},
+ {{kClientIp1 + kLbToken2, kHostname2, kUser3,
+ ::grpc::load_reporter::kCallStatusClientError},
+ 546}}));
+ vdm2.emplace(::grpc::load_reporter::kViewEndBytesSent,
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewEndBytesSent),
+ {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusOk},
+ 747},
+ {{kClientIp1 + kLbToken2, kHostname2, kUser3,
+ ::grpc::load_reporter::kCallStatusClientError},
+ 229}}));
+ vdm2.emplace(::grpc::load_reporter::kViewEndBytesReceived,
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewEndBytesReceived),
+ {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusOk},
+ 173},
+ {{kClientIp1 + kLbToken2, kHostname2, kUser3,
+ ::grpc::load_reporter::kCallStatusClientError},
+ 438}}));
+ vdm2.emplace(::grpc::load_reporter::kViewEndLatencyMs,
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewEndLatencyMs),
+ {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
+ ::grpc::load_reporter::kCallStatusOk},
+ 187},
+ {{kClientIp1 + kLbToken2, kHostname2, kUser3,
+ ::grpc::load_reporter::kCallStatusClientError},
+ 34}}));
+ vdm2.emplace(
+ ::grpc::load_reporter::kViewOtherCallMetricCount,
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewOtherCallMetricCount),
+ {{{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric1}, 1},
+ {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric2},
+ 1}}));
+ vdm2.emplace(
+ ::grpc::load_reporter::kViewOtherCallMetricValue,
+ ::opencensus::stats::testing::TestUtils::MakeViewData(
+ mock_census_view_provider()->FindViewDescriptor(
+ ::grpc::load_reporter::kViewOtherCallMetricValue),
+ {{{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric1}, 9.6},
+ {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric2},
+ 5.7}}));
+ // Set up mock expectation.
+ EXPECT_CALL(*mock_census_view_provider(), FetchViewData())
+ .WillOnce(Return(vdm1))
+ .WillOnce(Return(vdm2));
+ PrepareCpuExpectation(2);
+ // Start testing.
+ load_reporter_->ReportStreamCreated(kHostname1, kLbId1, kLoadKey1);
+ load_reporter_->ReportStreamCreated(kHostname2, kLbId2, kLoadKey2);
+ load_reporter_->ReportStreamCreated(kHostname2, kLbId3, kLoadKey3);
+ // First fetch.
+ load_reporter_->FetchAndSample();
+ load_reporter_->GenerateLoads(kHostname1, kLbId1);
+ gpr_log(GPR_INFO, "First load generated.");
+ // Second fetch.
+ load_reporter_->FetchAndSample();
+ load_reporter_->GenerateLoads(kHostname2, kLbId2);
+ gpr_log(GPR_INFO, "Second load generated.");
+ // TODO(juanlishen): Verify the data.
+}
+
+} // namespace
+} // namespace testing
+} // namespace grpc
+
+int main(int argc, char** argv) {
+ grpc_test_init(argc, argv);
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc
index fbc9f1501c..ee310784c2 100644
--- a/test/cpp/util/channel_trace_proto_helper.cc
+++ b/test/cpp/util/channel_trace_proto_helper.cc
@@ -30,26 +30,47 @@
namespace grpc {
namespace testing {
-void ValidateChannelTraceProtoJsonTranslation(char* tracer_json_c_str) {
- std::string tracer_json_str(tracer_json_c_str);
- grpc::channelz::ChannelTrace channel_trace;
+namespace {
+
+// Generic helper that takes in a json string, converts it to a proto, and
+// then back to json. This ensures that the json string was correctly formatted
+// according to https://developers.google.com/protocol-buffers/docs/proto3#json
+template <typename Message>
+void VaidateProtoJsonTranslation(char* json_c_str) {
+ std::string json_str(json_c_str);
+ Message msg;
google::protobuf::util::JsonParseOptions parse_options;
// If the following line is failing, then uncomment the last line of the
// comment, and uncomment the lines that print the two strings. You can
// then compare the output, and determine what fields are missing.
//
- // options.ignore_unknown_fields = true;
- ASSERT_EQ(google::protobuf::util::JsonStringToMessage(
- tracer_json_str, &channel_trace, parse_options),
+ // parse_options.ignore_unknown_fields = true;
+ EXPECT_EQ(google::protobuf::util::JsonStringToMessage(json_str, &msg,
+ parse_options),
google::protobuf::util::Status::OK);
std::string proto_json_str;
- ASSERT_EQ(google::protobuf::util::MessageToJsonString(channel_trace,
- &proto_json_str),
+ google::protobuf::util::JsonPrintOptions print_options;
+ // We usually do not want this to be true, however it can be helpful to
+ // uncomment and see the output produced then all fields are printed.
+ // print_options.always_print_primitive_fields = true;
+ EXPECT_EQ(google::protobuf::util::MessageToJsonString(msg, &proto_json_str,
+ print_options),
google::protobuf::util::Status::OK);
// uncomment these to compare the the json strings.
- // gpr_log(GPR_ERROR, "tracer json: %s", tracer_json_str.c_str());
+ // gpr_log(GPR_ERROR, "tracer json: %s", json_str.c_str());
// gpr_log(GPR_ERROR, "proto json: %s", proto_json_str.c_str());
- ASSERT_EQ(tracer_json_str, proto_json_str);
+ EXPECT_EQ(json_str, proto_json_str);
+}
+
+} // namespace
+
+void ValidateChannelTraceProtoJsonTranslation(char* tracer_json_c_str) {
+ VaidateProtoJsonTranslation<grpc::channelz::v1::ChannelTrace>(
+ tracer_json_c_str);
+}
+
+void ValidateChannelProtoJsonTranslation(char* channel_json_c_str) {
+ VaidateProtoJsonTranslation<grpc::channelz::v1::Channel>(channel_json_c_str);
}
} // namespace testing
diff --git a/test/cpp/util/channel_trace_proto_helper.h b/test/cpp/util/channel_trace_proto_helper.h
index d7043d9f06..d1a3603372 100644
--- a/test/cpp/util/channel_trace_proto_helper.h
+++ b/test/cpp/util/channel_trace_proto_helper.h
@@ -23,6 +23,7 @@ namespace grpc {
namespace testing {
void ValidateChannelTraceProtoJsonTranslation(char* tracer_json_c_str);
+void ValidateChannelProtoJsonTranslation(char* channel_json_c_str);
} // namespace testing
} // namespace grpc
diff --git a/test/distrib/python/test_packages.sh b/test/distrib/python/test_packages.sh
index 6bf49d45b9..755daa1021 100755
--- a/test/distrib/python/test_packages.sh
+++ b/test/distrib/python/test_packages.sh
@@ -28,10 +28,12 @@ else
echo "Testing Python source distribution"
ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-[0-9]*.tar.gz)
TOOLS_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-tools-[0-9]*.tar.gz)
- HEALTH_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-health-checking-[0-9]*.tar.gz)
- REFLECTION_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-reflection-[0-9]*.tar.gz)
fi
+HEALTH_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-health-checking-[0-9]*.tar.gz)
+REFLECTION_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-reflection-[0-9]*.tar.gz)
+TESTING_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-testing-[0-9]*.tar.gz)
+
VIRTUAL_ENV=$(mktemp -d)
virtualenv "$VIRTUAL_ENV"
PYTHON=$VIRTUAL_ENV/bin/python
@@ -53,13 +55,9 @@ function at_least_one_installs() {
at_least_one_installs "${ARCHIVES[@]}"
at_least_one_installs "${TOOLS_ARCHIVES[@]}"
-
-if [[ "$1" == "source" ]]
-then
- echo "Testing Python health and reflection packages"
- at_least_one_installs "${HEALTH_ARCHIVES[@]}"
- at_least_one_installs "${REFLECTION_ARCHIVES[@]}"
-fi
+at_least_one_installs "${HEALTH_ARCHIVES[@]}"
+at_least_one_installs "${REFLECTION_ARCHIVES[@]}"
+at_least_one_installs "${TESTING_ARCHIVES[@]}"
#