xref: /aosp_15_r20/system/chre/util/tests/transaction_manager_test.cc (revision 84e339476a462649f82315436d70fd732297a399)
1*84e33947SAndroid Build Coastguard Worker /*
2*84e33947SAndroid Build Coastguard Worker  * Copyright (C) 2024 The Android Open Source Project
3*84e33947SAndroid Build Coastguard Worker  *
4*84e33947SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*84e33947SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*84e33947SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*84e33947SAndroid Build Coastguard Worker  *
8*84e33947SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*84e33947SAndroid Build Coastguard Worker  *
10*84e33947SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*84e33947SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*84e33947SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*84e33947SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*84e33947SAndroid Build Coastguard Worker  * limitations under the License.
15*84e33947SAndroid Build Coastguard Worker  */
16*84e33947SAndroid Build Coastguard Worker 
17*84e33947SAndroid Build Coastguard Worker #include "chre/util/system/transaction_manager.h"
18*84e33947SAndroid Build Coastguard Worker 
19*84e33947SAndroid Build Coastguard Worker #include <algorithm>
20*84e33947SAndroid Build Coastguard Worker #include <map>
21*84e33947SAndroid Build Coastguard Worker 
22*84e33947SAndroid Build Coastguard Worker #include "chre/core/event_loop_common.h"
23*84e33947SAndroid Build Coastguard Worker #include "chre/core/timer_pool.h"
24*84e33947SAndroid Build Coastguard Worker #include "chre/platform/linux/system_time.h"
25*84e33947SAndroid Build Coastguard Worker 
26*84e33947SAndroid Build Coastguard Worker #include "gmock/gmock.h"
27*84e33947SAndroid Build Coastguard Worker #include "gtest/gtest.h"
28*84e33947SAndroid Build Coastguard Worker 
29*84e33947SAndroid Build Coastguard Worker using chre::platform_linux::SystemTimeOverride;
30*84e33947SAndroid Build Coastguard Worker using testing::_;
31*84e33947SAndroid Build Coastguard Worker using testing::Return;
32*84e33947SAndroid Build Coastguard Worker 
33*84e33947SAndroid Build Coastguard Worker namespace chre {
34*84e33947SAndroid Build Coastguard Worker namespace {
35*84e33947SAndroid Build Coastguard Worker 
36*84e33947SAndroid Build Coastguard Worker constexpr size_t kMaxTransactions = 32;
37*84e33947SAndroid Build Coastguard Worker constexpr Nanoseconds kTimeout = Milliseconds(10);
38*84e33947SAndroid Build Coastguard Worker constexpr uint16_t kMaxAttempts = 3;
39*84e33947SAndroid Build Coastguard Worker 
40*84e33947SAndroid Build Coastguard Worker }  // anonymous namespace
41*84e33947SAndroid Build Coastguard Worker 
42*84e33947SAndroid Build Coastguard Worker class MockTimerPool {
43*84e33947SAndroid Build Coastguard Worker  public:
44*84e33947SAndroid Build Coastguard Worker   MOCK_METHOD(TimerHandle, setSystemTimer,
45*84e33947SAndroid Build Coastguard Worker               (Nanoseconds, SystemEventCallbackFunction, SystemCallbackType,
46*84e33947SAndroid Build Coastguard Worker                void *));
47*84e33947SAndroid Build Coastguard Worker   MOCK_METHOD(bool, cancelSystemTimer, (TimerHandle));
48*84e33947SAndroid Build Coastguard Worker };
49*84e33947SAndroid Build Coastguard Worker 
50*84e33947SAndroid Build Coastguard Worker class FakeTimerPool {
51*84e33947SAndroid Build Coastguard Worker  public:
setSystemTimer(Nanoseconds duration,SystemEventCallbackFunction * callback,SystemCallbackType,void * data)52*84e33947SAndroid Build Coastguard Worker   TimerHandle setSystemTimer(Nanoseconds duration,
53*84e33947SAndroid Build Coastguard Worker                              SystemEventCallbackFunction *callback,
54*84e33947SAndroid Build Coastguard Worker                              SystemCallbackType /*callbackType*/, void *data) {
55*84e33947SAndroid Build Coastguard Worker     Timer timer = {
56*84e33947SAndroid Build Coastguard Worker         .expiry = SystemTime::getMonotonicTime() + duration,
57*84e33947SAndroid Build Coastguard Worker         .callback = callback,
58*84e33947SAndroid Build Coastguard Worker         .data = data,
59*84e33947SAndroid Build Coastguard Worker     };
60*84e33947SAndroid Build Coastguard Worker     TimerHandle handle = mNextHandle++;
61*84e33947SAndroid Build Coastguard Worker     mTimers[handle] = timer;
62*84e33947SAndroid Build Coastguard Worker     return handle;
63*84e33947SAndroid Build Coastguard Worker   }
cancelSystemTimer(TimerHandle handle)64*84e33947SAndroid Build Coastguard Worker   bool cancelSystemTimer(TimerHandle handle) {
65*84e33947SAndroid Build Coastguard Worker     return mTimers.erase(handle) == 1;
66*84e33947SAndroid Build Coastguard Worker   }
67*84e33947SAndroid Build Coastguard Worker 
68*84e33947SAndroid Build Coastguard Worker   //! Advance the time to the next expiring timer and invoke its callback
69*84e33947SAndroid Build Coastguard Worker   //! @return false if no timers exist
invokeNextTimer(SystemTimeOverride & time,Nanoseconds additionalDelay=Nanoseconds (0))70*84e33947SAndroid Build Coastguard Worker   bool invokeNextTimer(SystemTimeOverride &time,
71*84e33947SAndroid Build Coastguard Worker                        Nanoseconds additionalDelay = Nanoseconds(0)) {
72*84e33947SAndroid Build Coastguard Worker     auto it = std::min_element(mTimers.begin(), mTimers.end(),
73*84e33947SAndroid Build Coastguard Worker                                [](const auto &a, const auto &b) {
74*84e33947SAndroid Build Coastguard Worker                                  return a.second.expiry < b.second.expiry;
75*84e33947SAndroid Build Coastguard Worker                                });
76*84e33947SAndroid Build Coastguard Worker     if (it == mTimers.end()) {
77*84e33947SAndroid Build Coastguard Worker       return false;
78*84e33947SAndroid Build Coastguard Worker     }
79*84e33947SAndroid Build Coastguard Worker     Timer timer = it->second;
80*84e33947SAndroid Build Coastguard Worker     mTimers.erase(it);
81*84e33947SAndroid Build Coastguard Worker     time.update(timer.expiry + additionalDelay);
82*84e33947SAndroid Build Coastguard Worker     timer.callback(/*type=*/0, timer.data, /*extraData=*/nullptr);
83*84e33947SAndroid Build Coastguard Worker     return true;
84*84e33947SAndroid Build Coastguard Worker   }
85*84e33947SAndroid Build Coastguard Worker 
86*84e33947SAndroid Build Coastguard Worker   struct Timer {
87*84e33947SAndroid Build Coastguard Worker     Nanoseconds expiry;
88*84e33947SAndroid Build Coastguard Worker     SystemEventCallbackFunction *callback;
89*84e33947SAndroid Build Coastguard Worker     void *data;
90*84e33947SAndroid Build Coastguard Worker   };
91*84e33947SAndroid Build Coastguard Worker 
92*84e33947SAndroid Build Coastguard Worker   TimerHandle mNextHandle = 1;
93*84e33947SAndroid Build Coastguard Worker   std::map<TimerHandle, Timer> mTimers;
94*84e33947SAndroid Build Coastguard Worker };
95*84e33947SAndroid Build Coastguard Worker 
96*84e33947SAndroid Build Coastguard Worker class MockTransactionManagerCallback : public TransactionManagerCallback {
97*84e33947SAndroid Build Coastguard Worker  public:
98*84e33947SAndroid Build Coastguard Worker   MOCK_METHOD(void, onTransactionAttempt, (uint32_t, uint16_t), (override));
99*84e33947SAndroid Build Coastguard Worker   MOCK_METHOD(void, onTransactionFailure, (uint32_t, uint16_t), (override));
100*84e33947SAndroid Build Coastguard Worker };
101*84e33947SAndroid Build Coastguard Worker 
102*84e33947SAndroid Build Coastguard Worker class FakeTransactionManagerCallback : public TransactionManagerCallback {
103*84e33947SAndroid Build Coastguard Worker  public:
onTransactionAttempt(uint32_t transactionId,uint16_t)104*84e33947SAndroid Build Coastguard Worker   void onTransactionAttempt(uint32_t transactionId,
105*84e33947SAndroid Build Coastguard Worker                             uint16_t /*groupId*/) override {
106*84e33947SAndroid Build Coastguard Worker     mTries.push_back(transactionId);
107*84e33947SAndroid Build Coastguard Worker   }
onTransactionFailure(uint32_t transactionId,uint16_t)108*84e33947SAndroid Build Coastguard Worker   void onTransactionFailure(uint32_t transactionId,
109*84e33947SAndroid Build Coastguard Worker                             uint16_t /*groupId*/) override {
110*84e33947SAndroid Build Coastguard Worker     mFailures.push_back(transactionId);
111*84e33947SAndroid Build Coastguard Worker   }
112*84e33947SAndroid Build Coastguard Worker 
113*84e33947SAndroid Build Coastguard Worker   std::vector<uint32_t> mTries;
114*84e33947SAndroid Build Coastguard Worker   std::vector<uint32_t> mFailures;
115*84e33947SAndroid Build Coastguard Worker };
116*84e33947SAndroid Build Coastguard Worker 
117*84e33947SAndroid Build Coastguard Worker using TxnMgr = TransactionManager<kMaxTransactions, MockTimerPool>;
118*84e33947SAndroid Build Coastguard Worker using TxnMgrF = TransactionManager<kMaxTransactions, FakeTimerPool>;
119*84e33947SAndroid Build Coastguard Worker 
120*84e33947SAndroid Build Coastguard Worker class TransactionManagerTest : public testing::Test {
121*84e33947SAndroid Build Coastguard Worker  public:
122*84e33947SAndroid Build Coastguard Worker  protected:
defaultTxnMgr()123*84e33947SAndroid Build Coastguard Worker   TxnMgr defaultTxnMgr() {
124*84e33947SAndroid Build Coastguard Worker     return TxnMgr(mFakeCb, mTimerPool, kTimeout, kMaxAttempts);
125*84e33947SAndroid Build Coastguard Worker   }
126*84e33947SAndroid Build Coastguard Worker 
defaultTxnMgrF()127*84e33947SAndroid Build Coastguard Worker   TxnMgrF defaultTxnMgrF() {
128*84e33947SAndroid Build Coastguard Worker     return TxnMgrF(mFakeCb, mFakeTimerPool, kTimeout, kMaxAttempts);
129*84e33947SAndroid Build Coastguard Worker   }
130*84e33947SAndroid Build Coastguard Worker 
131*84e33947SAndroid Build Coastguard Worker   static constexpr uint32_t kTimerId = 1;
132*84e33947SAndroid Build Coastguard Worker 
133*84e33947SAndroid Build Coastguard Worker   MockTimerPool mTimerPool;
134*84e33947SAndroid Build Coastguard Worker   FakeTimerPool mFakeTimerPool;
135*84e33947SAndroid Build Coastguard Worker   FakeTransactionManagerCallback mFakeCb;
136*84e33947SAndroid Build Coastguard Worker   MockTransactionManagerCallback mMockCb;
137*84e33947SAndroid Build Coastguard Worker   SystemTimeOverride mTime = SystemTimeOverride(0);
138*84e33947SAndroid Build Coastguard Worker };
139*84e33947SAndroid Build Coastguard Worker 
TEST_F(TransactionManagerTest,StartSingleTransaction)140*84e33947SAndroid Build Coastguard Worker TEST_F(TransactionManagerTest, StartSingleTransaction) {
141*84e33947SAndroid Build Coastguard Worker   TxnMgr tm = defaultTxnMgr();
142*84e33947SAndroid Build Coastguard Worker 
143*84e33947SAndroid Build Coastguard Worker   EXPECT_CALL(mTimerPool, setSystemTimer(kTimeout, _, _, _))
144*84e33947SAndroid Build Coastguard Worker       .Times(1)
145*84e33947SAndroid Build Coastguard Worker       .WillOnce(Return(kTimerId));
146*84e33947SAndroid Build Coastguard Worker 
147*84e33947SAndroid Build Coastguard Worker   uint32_t id;
148*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.add(/*groupId=*/0, &id));
149*84e33947SAndroid Build Coastguard Worker 
150*84e33947SAndroid Build Coastguard Worker   ASSERT_EQ(mFakeCb.mTries.size(), 1);
151*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries[0], id);
152*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mFailures.size(), 0);
153*84e33947SAndroid Build Coastguard Worker }
154*84e33947SAndroid Build Coastguard Worker 
TEST_F(TransactionManagerTest,RemoveSingleTransaction)155*84e33947SAndroid Build Coastguard Worker TEST_F(TransactionManagerTest, RemoveSingleTransaction) {
156*84e33947SAndroid Build Coastguard Worker   TxnMgr tm = defaultTxnMgr();
157*84e33947SAndroid Build Coastguard Worker 
158*84e33947SAndroid Build Coastguard Worker   EXPECT_CALL(mTimerPool, setSystemTimer(_, _, _, _))
159*84e33947SAndroid Build Coastguard Worker       .Times(1)
160*84e33947SAndroid Build Coastguard Worker       .WillOnce(Return(kTimerId));
161*84e33947SAndroid Build Coastguard Worker 
162*84e33947SAndroid Build Coastguard Worker   uint32_t id;
163*84e33947SAndroid Build Coastguard Worker   ASSERT_TRUE(tm.add(/*groupId=*/0, &id));
164*84e33947SAndroid Build Coastguard Worker 
165*84e33947SAndroid Build Coastguard Worker   EXPECT_CALL(mTimerPool, cancelSystemTimer(kTimerId))
166*84e33947SAndroid Build Coastguard Worker       .Times(1)
167*84e33947SAndroid Build Coastguard Worker       .WillOnce(Return(true));
168*84e33947SAndroid Build Coastguard Worker 
169*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.remove(id));
170*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries.size(), 1);
171*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mFailures.size(), 0);
172*84e33947SAndroid Build Coastguard Worker }
173*84e33947SAndroid Build Coastguard Worker 
TEST_F(TransactionManagerTest,SingleTransactionSuccessOnRetry)174*84e33947SAndroid Build Coastguard Worker TEST_F(TransactionManagerTest, SingleTransactionSuccessOnRetry) {
175*84e33947SAndroid Build Coastguard Worker   TxnMgrF tm = defaultTxnMgrF();
176*84e33947SAndroid Build Coastguard Worker 
177*84e33947SAndroid Build Coastguard Worker   uint32_t id;
178*84e33947SAndroid Build Coastguard Worker   ASSERT_TRUE(tm.add(0, &id));
179*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(mFakeTimerPool.invokeNextTimer(mTime));
180*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries.size(), 2);
181*84e33947SAndroid Build Coastguard Worker 
182*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.remove(id));
183*84e33947SAndroid Build Coastguard Worker   ASSERT_EQ(mFakeCb.mTries.size(), 2);
184*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries[0], id);
185*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries[1], id);
186*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mFailures.size(), 0);
187*84e33947SAndroid Build Coastguard Worker   EXPECT_FALSE(mFakeTimerPool.invokeNextTimer(mTime));
188*84e33947SAndroid Build Coastguard Worker }
189*84e33947SAndroid Build Coastguard Worker 
TEST_F(TransactionManagerTest,SingleTransactionTimeout)190*84e33947SAndroid Build Coastguard Worker TEST_F(TransactionManagerTest, SingleTransactionTimeout) {
191*84e33947SAndroid Build Coastguard Worker   TxnMgrF tm = defaultTxnMgrF();
192*84e33947SAndroid Build Coastguard Worker 
193*84e33947SAndroid Build Coastguard Worker   uint32_t id;
194*84e33947SAndroid Build Coastguard Worker   ASSERT_TRUE(tm.add(0, &id));
195*84e33947SAndroid Build Coastguard Worker   size_t count = 0;
196*84e33947SAndroid Build Coastguard Worker   while (mFakeTimerPool.invokeNextTimer(mTime) && count++ < kMaxAttempts * 2);
197*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(count, kMaxAttempts);
198*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(std::count(mFakeCb.mTries.begin(), mFakeCb.mTries.end(), id),
199*84e33947SAndroid Build Coastguard Worker             kMaxAttempts);
200*84e33947SAndroid Build Coastguard Worker   ASSERT_EQ(mFakeCb.mFailures.size(), 1);
201*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mFailures[0], id);
202*84e33947SAndroid Build Coastguard Worker 
203*84e33947SAndroid Build Coastguard Worker   // The transaction should actually be gone
204*84e33947SAndroid Build Coastguard Worker   EXPECT_FALSE(tm.remove(id));
205*84e33947SAndroid Build Coastguard Worker   EXPECT_FALSE(mFakeTimerPool.invokeNextTimer(mTime));
206*84e33947SAndroid Build Coastguard Worker }
207*84e33947SAndroid Build Coastguard Worker 
TEST_F(TransactionManagerTest,TwoTransactionsDifferentGroups)208*84e33947SAndroid Build Coastguard Worker TEST_F(TransactionManagerTest, TwoTransactionsDifferentGroups) {
209*84e33947SAndroid Build Coastguard Worker   TxnMgrF tm = defaultTxnMgrF();
210*84e33947SAndroid Build Coastguard Worker 
211*84e33947SAndroid Build Coastguard Worker   uint32_t id1;
212*84e33947SAndroid Build Coastguard Worker   uint32_t id2;
213*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.add(/*groupId=*/0, &id1));
214*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.add(/*groupId=*/1, &id2));
215*84e33947SAndroid Build Coastguard Worker 
216*84e33947SAndroid Build Coastguard Worker   // Both should start
217*84e33947SAndroid Build Coastguard Worker   ASSERT_EQ(mFakeCb.mTries.size(), 2);
218*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries[0], id1);
219*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries[1], id2);
220*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mFailures.size(), 0);
221*84e33947SAndroid Build Coastguard Worker }
222*84e33947SAndroid Build Coastguard Worker 
TEST_F(TransactionManagerTest,TwoTransactionsSameGroup)223*84e33947SAndroid Build Coastguard Worker TEST_F(TransactionManagerTest, TwoTransactionsSameGroup) {
224*84e33947SAndroid Build Coastguard Worker   TxnMgrF tm = defaultTxnMgrF();
225*84e33947SAndroid Build Coastguard Worker 
226*84e33947SAndroid Build Coastguard Worker   uint32_t id1;
227*84e33947SAndroid Build Coastguard Worker   uint32_t id2;
228*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.add(/*groupId=*/0, &id1));
229*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.add(/*groupId=*/0, &id2));
230*84e33947SAndroid Build Coastguard Worker 
231*84e33947SAndroid Build Coastguard Worker   // Only the first should start
232*84e33947SAndroid Build Coastguard Worker   ASSERT_EQ(mFakeCb.mTries.size(), 1);
233*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries[0], id1);
234*84e33947SAndroid Build Coastguard Worker 
235*84e33947SAndroid Build Coastguard Worker   // Second starts after the first finishes
236*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.remove(id1));
237*84e33947SAndroid Build Coastguard Worker   ASSERT_EQ(mFakeCb.mTries.size(), 2);
238*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries[1], id2);
239*84e33947SAndroid Build Coastguard Worker 
240*84e33947SAndroid Build Coastguard Worker   // Second completes with no funny business
241*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.remove(id2));
242*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries.size(), 2);
243*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mFailures.size(), 0);
244*84e33947SAndroid Build Coastguard Worker   EXPECT_FALSE(mFakeTimerPool.invokeNextTimer(mTime));
245*84e33947SAndroid Build Coastguard Worker }
246*84e33947SAndroid Build Coastguard Worker 
TEST_F(TransactionManagerTest,TwoTransactionsSameGroupTimeout)247*84e33947SAndroid Build Coastguard Worker TEST_F(TransactionManagerTest, TwoTransactionsSameGroupTimeout) {
248*84e33947SAndroid Build Coastguard Worker   TxnMgrF tm = defaultTxnMgrF();
249*84e33947SAndroid Build Coastguard Worker 
250*84e33947SAndroid Build Coastguard Worker   uint32_t id1;
251*84e33947SAndroid Build Coastguard Worker   uint32_t id2;
252*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.add(/*groupId=*/0, &id1));
253*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.add(/*groupId=*/0, &id2));
254*84e33947SAndroid Build Coastguard Worker 
255*84e33947SAndroid Build Coastguard Worker   // Time out the first transaction, which should kick off the second
256*84e33947SAndroid Build Coastguard Worker   for (size_t i = 0; i < kMaxAttempts; i++) {
257*84e33947SAndroid Build Coastguard Worker     EXPECT_TRUE(mFakeTimerPool.invokeNextTimer(mTime));
258*84e33947SAndroid Build Coastguard Worker   }
259*84e33947SAndroid Build Coastguard Worker   ASSERT_EQ(mFakeCb.mTries.size(), kMaxAttempts + 1);
260*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(std::count(mFakeCb.mTries.begin(), mFakeCb.mTries.end(), id1),
261*84e33947SAndroid Build Coastguard Worker             kMaxAttempts);
262*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries.back(), id2);
263*84e33947SAndroid Build Coastguard Worker 
264*84e33947SAndroid Build Coastguard Worker   // Retry + time out behavior for second works the same as the first
265*84e33947SAndroid Build Coastguard Worker   for (size_t i = 0; i < kMaxAttempts; i++) {
266*84e33947SAndroid Build Coastguard Worker     EXPECT_TRUE(mFakeTimerPool.invokeNextTimer(mTime));
267*84e33947SAndroid Build Coastguard Worker   }
268*84e33947SAndroid Build Coastguard Worker   ASSERT_EQ(mFakeCb.mTries.size(), kMaxAttempts * 2);
269*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(std::count(mFakeCb.mTries.begin(), mFakeCb.mTries.end(), id2),
270*84e33947SAndroid Build Coastguard Worker             kMaxAttempts);
271*84e33947SAndroid Build Coastguard Worker   ASSERT_EQ(mFakeCb.mFailures.size(), 2);
272*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mFailures[0], id1);
273*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mFailures[1], id2);
274*84e33947SAndroid Build Coastguard Worker   EXPECT_FALSE(mFakeTimerPool.invokeNextTimer(mTime));
275*84e33947SAndroid Build Coastguard Worker }
276*84e33947SAndroid Build Coastguard Worker 
TEST_F(TransactionManagerTest,TwoTransactionsSameGroupRemoveReverseOrder)277*84e33947SAndroid Build Coastguard Worker TEST_F(TransactionManagerTest, TwoTransactionsSameGroupRemoveReverseOrder) {
278*84e33947SAndroid Build Coastguard Worker   TxnMgrF tm = defaultTxnMgrF();
279*84e33947SAndroid Build Coastguard Worker 
280*84e33947SAndroid Build Coastguard Worker   uint32_t id1;
281*84e33947SAndroid Build Coastguard Worker   uint32_t id2;
282*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.add(/*groupId=*/0, &id1));
283*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.add(/*groupId=*/0, &id2));
284*84e33947SAndroid Build Coastguard Worker 
285*84e33947SAndroid Build Coastguard Worker   // Only the first should start
286*84e33947SAndroid Build Coastguard Worker   ASSERT_EQ(mFakeCb.mTries.size(), 1);
287*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries[0], id1);
288*84e33947SAndroid Build Coastguard Worker 
289*84e33947SAndroid Build Coastguard Worker   // Remove second one first
290*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.remove(id2));
291*84e33947SAndroid Build Coastguard Worker 
292*84e33947SAndroid Build Coastguard Worker   // Finish the first one
293*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.remove(id1));
294*84e33947SAndroid Build Coastguard Worker   ASSERT_EQ(mFakeCb.mTries.size(), 1);
295*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries[0], id1);
296*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mFailures.size(), 0);
297*84e33947SAndroid Build Coastguard Worker   EXPECT_FALSE(mFakeTimerPool.invokeNextTimer(mTime));
298*84e33947SAndroid Build Coastguard Worker }
299*84e33947SAndroid Build Coastguard Worker 
TEST_F(TransactionManagerTest,MultipleTimeouts)300*84e33947SAndroid Build Coastguard Worker TEST_F(TransactionManagerTest, MultipleTimeouts) {
301*84e33947SAndroid Build Coastguard Worker   TxnMgrF tm = defaultTxnMgrF();
302*84e33947SAndroid Build Coastguard Worker 
303*84e33947SAndroid Build Coastguard Worker   // Timeout both in a single callback
304*84e33947SAndroid Build Coastguard Worker   uint32_t ids[2];
305*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.add(/*groupId=*/0, &ids[0]));
306*84e33947SAndroid Build Coastguard Worker   mTime.update(kTimeout.toRawNanoseconds() / 2);
307*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(tm.add(/*groupId=*/1, &ids[1]));
308*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(mFakeTimerPool.invokeNextTimer(mTime, kTimeout));
309*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries.size(), 4);
310*84e33947SAndroid Build Coastguard Worker 
311*84e33947SAndroid Build Coastguard Worker   // Since both retries were dispatched at the same time, they should time out
312*84e33947SAndroid Build Coastguard Worker   // again together
313*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(mFakeTimerPool.invokeNextTimer(mTime, kTimeout));
314*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries.size(), 6);
315*84e33947SAndroid Build Coastguard Worker 
316*84e33947SAndroid Build Coastguard Worker   // If changing the max # of attempts, modify the below code too so it triggers
317*84e33947SAndroid Build Coastguard Worker   // failure
318*84e33947SAndroid Build Coastguard Worker   static_assert(kMaxAttempts == 3);
319*84e33947SAndroid Build Coastguard Worker   EXPECT_TRUE(mFakeTimerPool.invokeNextTimer(mTime, kTimeout));
320*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mTries.size(), 6);
321*84e33947SAndroid Build Coastguard Worker   for (size_t i = 0; i < mFakeCb.mTries.size(); i++) {
322*84e33947SAndroid Build Coastguard Worker     EXPECT_EQ(mFakeCb.mTries[i], ids[i % 2]);
323*84e33947SAndroid Build Coastguard Worker   }
324*84e33947SAndroid Build Coastguard Worker   ASSERT_EQ(mFakeCb.mFailures.size(), 2);
325*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mFailures[0], ids[0]);
326*84e33947SAndroid Build Coastguard Worker   EXPECT_EQ(mFakeCb.mFailures[1], ids[1]);
327*84e33947SAndroid Build Coastguard Worker   EXPECT_FALSE(mFakeTimerPool.invokeNextTimer(mTime));
328*84e33947SAndroid Build Coastguard Worker }
329*84e33947SAndroid Build Coastguard Worker 
TEST_F(TransactionManagerTest,CallbackUsesCorrectGroupId)330*84e33947SAndroid Build Coastguard Worker TEST_F(TransactionManagerTest, CallbackUsesCorrectGroupId) {
331*84e33947SAndroid Build Coastguard Worker   TxnMgrF tm(mMockCb, mFakeTimerPool, kTimeout, /*maxAttempts=*/1);
332*84e33947SAndroid Build Coastguard Worker 
333*84e33947SAndroid Build Coastguard Worker   EXPECT_CALL(mMockCb, onTransactionAttempt(_, 1)).Times(1);
334*84e33947SAndroid Build Coastguard Worker   EXPECT_CALL(mMockCb, onTransactionAttempt(_, 2)).Times(1);
335*84e33947SAndroid Build Coastguard Worker   EXPECT_CALL(mMockCb, onTransactionAttempt(_, 3)).Times(1);
336*84e33947SAndroid Build Coastguard Worker 
337*84e33947SAndroid Build Coastguard Worker   uint32_t id;
338*84e33947SAndroid Build Coastguard Worker   tm.add(1, &id);
339*84e33947SAndroid Build Coastguard Worker   tm.add(2, &id);
340*84e33947SAndroid Build Coastguard Worker   tm.add(3, &id);
341*84e33947SAndroid Build Coastguard Worker 
342*84e33947SAndroid Build Coastguard Worker   EXPECT_CALL(mMockCb, onTransactionFailure(_, 1)).Times(1);
343*84e33947SAndroid Build Coastguard Worker   EXPECT_CALL(mMockCb, onTransactionFailure(_, 2)).Times(1);
344*84e33947SAndroid Build Coastguard Worker   EXPECT_CALL(mMockCb, onTransactionFailure(_, 3)).Times(1);
345*84e33947SAndroid Build Coastguard Worker 
346*84e33947SAndroid Build Coastguard Worker   mFakeTimerPool.invokeNextTimer(mTime);
347*84e33947SAndroid Build Coastguard Worker   mFakeTimerPool.invokeNextTimer(mTime);
348*84e33947SAndroid Build Coastguard Worker   mFakeTimerPool.invokeNextTimer(mTime);
349*84e33947SAndroid Build Coastguard Worker }
350*84e33947SAndroid Build Coastguard Worker 
351*84e33947SAndroid Build Coastguard Worker }  // namespace chre
352