aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/core/gprpp
diff options
context:
space:
mode:
authorGravatar kpayson64 <kpayson@google.com>2018-04-30 17:40:00 -0700
committerGravatar kpayson64 <kpayson@google.com>2018-04-30 17:40:59 -0700
commit701e70da071ef91152c30aad813e2ed405c05c59 (patch)
tree10a6191128838bfb380d510567b2e047f6c9bb04 /test/core/gprpp
parent38ab21ee0996a54c682488bcf43ecf5ba0f7f24a (diff)
c++ify
Diffstat (limited to 'test/core/gprpp')
-rw-r--r--test/core/gprpp/fork_test.cc136
1 files changed, 136 insertions, 0 deletions
diff --git a/test/core/gprpp/fork_test.cc b/test/core/gprpp/fork_test.cc
new file mode 100644
index 0000000000..c4a8a4e5f5
--- /dev/null
+++ b/test/core/gprpp/fork_test.cc
@@ -0,0 +1,136 @@
+/*
+ *
+ * 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 "src/core/lib/gprpp/fork.h"
+
+#include "src/core/lib/gprpp/thd.h"
+#include "test/core/util/test_config.h"
+
+static void test_init() {
+ GPR_ASSERT(!grpc_core::Fork::Enabled());
+
+ // Default fork support (disabled)
+ grpc_core::Fork::GlobalInit();
+ GPR_ASSERT(!grpc_core::Fork::Enabled());
+ grpc_core::Fork::GlobalShutdown();
+
+ // Explicitly disabled fork support
+ grpc_core::Fork::Enable(false);
+ grpc_core::Fork::GlobalInit();
+ GPR_ASSERT(!grpc_core::Fork::Enabled());
+ grpc_core::Fork::GlobalShutdown();
+
+ // Explicitly enabled fork support
+ grpc_core::Fork::Enable(true);
+ grpc_core::Fork::GlobalInit();
+ GPR_ASSERT(grpc_core::Fork::Enabled());
+ grpc_core::Fork::GlobalShutdown();
+}
+
+#define THREAD_DELAY_MS 3000
+#define THREAD_DELAY_EPSILON 500
+#define CONCURRENT_TEST_THREADS 100
+
+static void sleeping_thd(void* arg) {
+ int64_t sleep_ms = (int64_t)arg;
+ gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_millis(sleep_ms, GPR_TIMESPAN)));
+}
+
+static void test_thd_count() {
+ // Test no active threads
+ grpc_core::Fork::Enable(true);
+ grpc_core::Fork::GlobalInit();
+ grpc_core::Fork::AwaitThreads();
+ grpc_core::Fork::GlobalShutdown();
+
+ grpc_core::Fork::Enable(true);
+ grpc_core::Fork::GlobalInit();
+ grpc_core::Thread thds[CONCURRENT_TEST_THREADS];
+ gpr_timespec est_end_time =
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_millis(THREAD_DELAY_MS, GPR_TIMESPAN));
+ gpr_timespec tolerance =
+ gpr_time_from_millis(THREAD_DELAY_EPSILON, GPR_TIMESPAN);
+ for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
+ intptr_t sleep_time_ms =
+ (i * THREAD_DELAY_MS) / (CONCURRENT_TEST_THREADS - 1);
+ thds[i] =
+ grpc_core::Thread("grpc_fork_test", sleeping_thd, (void*)sleep_time_ms);
+ thds[i].Start();
+ }
+ grpc_core::Fork::AwaitThreads();
+ gpr_timespec end_time = gpr_now(GPR_CLOCK_REALTIME);
+ for (auto& thd : thds) {
+ thd.Join();
+ }
+ GPR_ASSERT(gpr_time_similar(end_time, est_end_time, tolerance));
+ grpc_core::Fork::GlobalShutdown();
+}
+
+static void exec_ctx_thread(void* arg) {
+ bool* exec_ctx_created = (bool*)arg;
+ grpc_core::Fork::IncExecCtxCount();
+ *exec_ctx_created = true;
+}
+
+static void test_exec_count() {
+ grpc_core::Fork::IncExecCtxCount();
+ grpc_core::Fork::Enable(true);
+ grpc_core::Fork::GlobalInit();
+
+ grpc_core::Fork::IncExecCtxCount();
+ GPR_ASSERT(grpc_core::Fork::BlockExecCtx());
+ grpc_core::Fork::DecExecCtxCount();
+ grpc_core::Fork::AllowExecCtx();
+
+ grpc_core::Fork::IncExecCtxCount();
+ grpc_core::Fork::IncExecCtxCount();
+ GPR_ASSERT(!grpc_core::Fork::BlockExecCtx());
+ grpc_core::Fork::DecExecCtxCount();
+ grpc_core::Fork::DecExecCtxCount();
+
+ grpc_core::Fork::IncExecCtxCount();
+ GPR_ASSERT(grpc_core::Fork::BlockExecCtx());
+ grpc_core::Fork::DecExecCtxCount();
+ grpc_core::Fork::AllowExecCtx();
+
+ // Test that block_exec_ctx() blocks grpc_core::Fork::IncExecCtxCount
+ bool exec_ctx_created = false;
+ grpc_core::Thread thd =
+ grpc_core::Thread("grpc_fork_test", exec_ctx_thread, &exec_ctx_created);
+ grpc_core::Fork::IncExecCtxCount();
+ GPR_ASSERT(grpc_core::Fork::BlockExecCtx());
+ grpc_core::Fork::DecExecCtxCount();
+ thd.Start();
+ gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_seconds(1, GPR_TIMESPAN)));
+ GPR_ASSERT(!exec_ctx_created);
+ grpc_core::Fork::AllowExecCtx();
+ thd.Join(); // This ensure that the call got un-blocked
+ grpc_core::Fork::GlobalShutdown();
+}
+
+int main(int argc, char* argv[]) {
+ grpc_test_init(argc, argv);
+ test_init();
+ test_thd_count();
+ test_exec_count();
+
+ return 0;
+}