xref: /aosp_15_r20/external/federated-compute/fcp/base/reentrancy_guard_test.cc (revision 14675a029014e728ec732f129a32e299b2da0601)
1*14675a02SAndroid Build Coastguard Worker // Copyright 2021 Google LLC
2*14675a02SAndroid Build Coastguard Worker //
3*14675a02SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*14675a02SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*14675a02SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*14675a02SAndroid Build Coastguard Worker //
7*14675a02SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
8*14675a02SAndroid Build Coastguard Worker //
9*14675a02SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*14675a02SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*14675a02SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*14675a02SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*14675a02SAndroid Build Coastguard Worker // limitations under the License.
14*14675a02SAndroid Build Coastguard Worker 
15*14675a02SAndroid Build Coastguard Worker #include "fcp/base/reentrancy_guard.h"
16*14675a02SAndroid Build Coastguard Worker 
17*14675a02SAndroid Build Coastguard Worker #include <atomic>
18*14675a02SAndroid Build Coastguard Worker 
19*14675a02SAndroid Build Coastguard Worker #include "gtest/gtest.h"
20*14675a02SAndroid Build Coastguard Worker #include "absl/synchronization/notification.h"
21*14675a02SAndroid Build Coastguard Worker #include "fcp/base/monitoring.h"
22*14675a02SAndroid Build Coastguard Worker #include "fcp/base/scheduler.h"
23*14675a02SAndroid Build Coastguard Worker #include "fcp/testing/testing.h"
24*14675a02SAndroid Build Coastguard Worker 
25*14675a02SAndroid Build Coastguard Worker namespace fcp {
26*14675a02SAndroid Build Coastguard Worker namespace {
27*14675a02SAndroid Build Coastguard Worker 
28*14675a02SAndroid Build Coastguard Worker class ReentrancyGuardTest : public testing::Test {
29*14675a02SAndroid Build Coastguard Worker  protected:
SimpleMethod()30*14675a02SAndroid Build Coastguard Worker   Status SimpleMethod() {
31*14675a02SAndroid Build Coastguard Worker     ReentrancyGuard guard;
32*14675a02SAndroid Build Coastguard Worker     return guard.Check(&in_use_);
33*14675a02SAndroid Build Coastguard Worker   }
34*14675a02SAndroid Build Coastguard Worker 
ReentrantMethod()35*14675a02SAndroid Build Coastguard Worker   Status ReentrantMethod() {
36*14675a02SAndroid Build Coastguard Worker     ReentrancyGuard guard;
37*14675a02SAndroid Build Coastguard Worker     FCP_RETURN_IF_ERROR((guard.Check(&in_use_)));
38*14675a02SAndroid Build Coastguard Worker     return ReentrantMethod();
39*14675a02SAndroid Build Coastguard Worker   }
40*14675a02SAndroid Build Coastguard Worker 
LongRunningMethod(absl::Notification * method_entered,absl::Notification * resume)41*14675a02SAndroid Build Coastguard Worker   Status LongRunningMethod(absl::Notification* method_entered,
42*14675a02SAndroid Build Coastguard Worker                            absl::Notification* resume) {
43*14675a02SAndroid Build Coastguard Worker     ReentrancyGuard guard;
44*14675a02SAndroid Build Coastguard Worker     FCP_RETURN_IF_ERROR((guard.Check(&in_use_)));
45*14675a02SAndroid Build Coastguard Worker     method_entered->Notify();
46*14675a02SAndroid Build Coastguard Worker     resume->WaitForNotification();
47*14675a02SAndroid Build Coastguard Worker     return FCP_STATUS(OK);
48*14675a02SAndroid Build Coastguard Worker   }
49*14675a02SAndroid Build Coastguard Worker 
50*14675a02SAndroid Build Coastguard Worker  private:
51*14675a02SAndroid Build Coastguard Worker   std::atomic<bool> in_use_ = false;
52*14675a02SAndroid Build Coastguard Worker };
53*14675a02SAndroid Build Coastguard Worker 
TEST_F(ReentrancyGuardTest,SequentialCallsSucceed)54*14675a02SAndroid Build Coastguard Worker TEST_F(ReentrancyGuardTest, SequentialCallsSucceed) {
55*14675a02SAndroid Build Coastguard Worker   ASSERT_THAT(SimpleMethod(), IsOk());
56*14675a02SAndroid Build Coastguard Worker   ASSERT_THAT(SimpleMethod(), IsOk());
57*14675a02SAndroid Build Coastguard Worker }
58*14675a02SAndroid Build Coastguard Worker 
TEST_F(ReentrancyGuardTest,ReentrantCallsFail)59*14675a02SAndroid Build Coastguard Worker TEST_F(ReentrancyGuardTest, ReentrantCallsFail) {
60*14675a02SAndroid Build Coastguard Worker   ASSERT_THAT(ReentrantMethod(), IsCode(FAILED_PRECONDITION));
61*14675a02SAndroid Build Coastguard Worker }
62*14675a02SAndroid Build Coastguard Worker 
TEST_F(ReentrancyGuardTest,ConcurrentCallsFail)63*14675a02SAndroid Build Coastguard Worker TEST_F(ReentrancyGuardTest, ConcurrentCallsFail) {
64*14675a02SAndroid Build Coastguard Worker   absl::Notification long_running_method_entered;
65*14675a02SAndroid Build Coastguard Worker   absl::Notification resume;
66*14675a02SAndroid Build Coastguard Worker 
67*14675a02SAndroid Build Coastguard Worker   auto pool = fcp::CreateThreadPoolScheduler(1);
68*14675a02SAndroid Build Coastguard Worker   pool->Schedule([&] {
69*14675a02SAndroid Build Coastguard Worker     ASSERT_THAT(LongRunningMethod(&long_running_method_entered, &resume),
70*14675a02SAndroid Build Coastguard Worker                 IsOk());
71*14675a02SAndroid Build Coastguard Worker   });
72*14675a02SAndroid Build Coastguard Worker 
73*14675a02SAndroid Build Coastguard Worker   // This signals that LongRunningMethod() has been entered and waits there
74*14675a02SAndroid Build Coastguard Worker   // to be resumed.
75*14675a02SAndroid Build Coastguard Worker   long_running_method_entered.WaitForNotification();
76*14675a02SAndroid Build Coastguard Worker 
77*14675a02SAndroid Build Coastguard Worker   // Make a concurrent call, which is expected to fail.
78*14675a02SAndroid Build Coastguard Worker   ASSERT_THAT(SimpleMethod(), IsCode(FAILED_PRECONDITION));
79*14675a02SAndroid Build Coastguard Worker 
80*14675a02SAndroid Build Coastguard Worker   // Resume LongRunningMethod() and wait for the thread to finish.
81*14675a02SAndroid Build Coastguard Worker   resume.Notify();
82*14675a02SAndroid Build Coastguard Worker   pool->WaitUntilIdle();
83*14675a02SAndroid Build Coastguard Worker }
84*14675a02SAndroid Build Coastguard Worker 
85*14675a02SAndroid Build Coastguard Worker }  // namespace
86*14675a02SAndroid Build Coastguard Worker }  // namespace fcp
87