Imported Upstream version 1.41.0
[platform/upstream/grpc.git] / test / core / iomgr / work_serializer_test.cc
1 /*
2  *
3  * Copyright 2019 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18
19 #include "src/core/lib/iomgr/work_serializer.h"
20
21 #include <memory>
22
23 #include <gtest/gtest.h>
24
25 #include "absl/memory/memory.h"
26
27 #include <grpc/grpc.h>
28 #include <grpc/support/alloc.h>
29 #include <grpc/support/log.h>
30
31 #include "src/core/lib/gpr/useful.h"
32 #include "src/core/lib/gprpp/thd.h"
33 #include "test/core/util/test_config.h"
34
35 namespace {
36 TEST(WorkSerializerTest, NoOp) { grpc_core::WorkSerializer lock; }
37
38 TEST(WorkSerializerTest, ExecuteOne) {
39   grpc_core::WorkSerializer lock;
40   gpr_event done;
41   gpr_event_init(&done);
42   lock.Run([&done]() { gpr_event_set(&done, reinterpret_cast<void*>(1)); },
43            DEBUG_LOCATION);
44   EXPECT_TRUE(gpr_event_wait(&done, grpc_timeout_seconds_to_deadline(5)) !=
45               nullptr);
46 }
47
48 class TestThread {
49  public:
50   explicit TestThread(grpc_core::WorkSerializer* lock)
51       : lock_(lock), thread_("grpc_execute_many", ExecuteManyLoop, this) {
52     gpr_event_init(&done_);
53     thread_.Start();
54   }
55
56   ~TestThread() {
57     EXPECT_NE(gpr_event_wait(&done_, gpr_inf_future(GPR_CLOCK_REALTIME)),
58               nullptr);
59     thread_.Join();
60   }
61
62  private:
63   static void ExecuteManyLoop(void* arg) {
64     TestThread* self = static_cast<TestThread*>(arg);
65     size_t n = 1;
66     for (size_t i = 0; i < 10; i++) {
67       for (size_t j = 0; j < 10000; j++) {
68         struct ExecutionArgs {
69           size_t* counter;
70           size_t value;
71         };
72         ExecutionArgs* c = new ExecutionArgs;
73         c->counter = &self->counter_;
74         c->value = n++;
75         self->lock_->Run(
76             [c]() {
77               EXPECT_TRUE(*c->counter == c->value - 1);
78               *c->counter = c->value;
79               delete c;
80             },
81             DEBUG_LOCATION);
82       }
83       // sleep for a little bit, to test other threads picking up the load
84       gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100));
85     }
86     self->lock_->Run(
87         [self]() { gpr_event_set(&self->done_, reinterpret_cast<void*>(1)); },
88         DEBUG_LOCATION);
89   }
90
91   grpc_core::WorkSerializer* lock_ = nullptr;
92   grpc_core::Thread thread_;
93   size_t counter_ = 0;
94   gpr_event done_;
95 };
96
97 TEST(WorkSerializerTest, ExecuteMany) {
98   grpc_core::WorkSerializer lock;
99   {
100     std::vector<std::unique_ptr<TestThread>> threads;
101     for (size_t i = 0; i < 100; ++i) {
102       threads.push_back(absl::make_unique<TestThread>(&lock));
103     }
104   }
105 }
106 }  // namespace
107
108 int main(int argc, char** argv) {
109   grpc::testing::TestEnvironment env(argc, argv);
110   grpc_init();
111   ::testing::InitGoogleTest(&argc, argv);
112   int retval = RUN_ALL_TESTS();
113   grpc_shutdown();
114   return retval;
115 }