1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "../AnrTracker.h"
18 
19 #include <binder/Binder.h>
20 #include <gtest/gtest.h>
21 
22 namespace android {
23 
24 namespace inputdispatcher {
25 
26 // --- AnrTrackerTest ---
27 
28 /**
29  * Add a single entry and ensure it's returned as first, even if the token isn't valid
30  */
TEST(AnrTrackerTest,SingleEntry_First)31 TEST(AnrTrackerTest, SingleEntry_First) {
32     AnrTracker tracker;
33 
34     tracker.insert(1, nullptr);
35 
36     ASSERT_EQ(1, tracker.firstTimeout());
37     ASSERT_EQ(tracker.firstToken(), nullptr);
38 }
39 
TEST(AnrTrackerTest,MultipleEntries_RemoveToken)40 TEST(AnrTrackerTest, MultipleEntries_RemoveToken) {
41     AnrTracker tracker;
42 
43     sp<IBinder> token1 = sp<BBinder>::make();
44     sp<IBinder> token2 = sp<BBinder>::make();
45 
46     tracker.insert(1, token1);
47     tracker.insert(2, token2);
48     tracker.insert(3, token1);
49     tracker.insert(4, token2);
50     tracker.insert(5, token1);
51 
52     tracker.eraseToken(token1);
53 
54     ASSERT_EQ(2, tracker.firstTimeout());
55 }
56 
TEST(AnrTrackerTest,AddAndRemove_Empty)57 TEST(AnrTrackerTest, AddAndRemove_Empty) {
58     AnrTracker tracker;
59 
60     ASSERT_TRUE(tracker.empty());
61 
62     tracker.insert(1, nullptr);
63     ASSERT_FALSE(tracker.empty());
64 
65     tracker.erase(1, nullptr);
66     ASSERT_TRUE(tracker.empty());
67 }
68 
TEST(AnrTrackerTest,Clear)69 TEST(AnrTrackerTest, Clear) {
70     AnrTracker tracker;
71 
72     tracker.insert(1, nullptr);
73     tracker.clear();
74     ASSERT_TRUE(tracker.empty());
75 }
76 
TEST(AnrTrackerTest,SingleToken_MaintainsOrder)77 TEST(AnrTrackerTest, SingleToken_MaintainsOrder) {
78     AnrTracker tracker;
79 
80     ASSERT_TRUE(tracker.empty());
81 
82     tracker.insert(2, nullptr);
83     tracker.insert(5, nullptr);
84     tracker.insert(0, nullptr);
85 
86     ASSERT_EQ(0, tracker.firstTimeout());
87     ASSERT_EQ(nullptr, tracker.firstToken());
88 }
89 
TEST(AnrTrackerTest,MultipleTokens_MaintainsOrder)90 TEST(AnrTrackerTest, MultipleTokens_MaintainsOrder) {
91     AnrTracker tracker;
92 
93     sp<IBinder> token1 = sp<BBinder>::make();
94     sp<IBinder> token2 = sp<BBinder>::make();
95 
96     tracker.insert(2, token1);
97     tracker.insert(5, token2);
98     tracker.insert(0, token2);
99 
100     ASSERT_EQ(0, tracker.firstTimeout());
101     ASSERT_EQ(token2, tracker.firstToken());
102 }
103 
TEST(AnrTrackerTest,MultipleTokens_IdenticalTimes)104 TEST(AnrTrackerTest, MultipleTokens_IdenticalTimes) {
105     AnrTracker tracker;
106 
107     sp<IBinder> token1 = sp<BBinder>::make();
108     sp<IBinder> token2 = sp<BBinder>::make();
109 
110     tracker.insert(2, token1);
111     tracker.insert(2, token2);
112     tracker.insert(10, token2);
113 
114     ASSERT_EQ(2, tracker.firstTimeout());
115     // Doesn't matter which token is returned - both are valid results
116     ASSERT_TRUE(token1 == tracker.firstToken() || token2 == tracker.firstToken());
117 }
118 
TEST(AnrTrackerTest,MultipleTokens_IdenticalTimesRemove)119 TEST(AnrTrackerTest, MultipleTokens_IdenticalTimesRemove) {
120     AnrTracker tracker;
121 
122     sp<IBinder> token1 = sp<BBinder>::make();
123     sp<IBinder> token2 = sp<BBinder>::make();
124 
125     tracker.insert(2, token1);
126     tracker.insert(2, token2);
127     tracker.insert(10, token2);
128 
129     tracker.erase(2, token2);
130 
131     ASSERT_EQ(2, tracker.firstTimeout());
132     ASSERT_EQ(token1, tracker.firstToken());
133 }
134 
TEST(AnrTrackerTest,Empty_DoesntCrash)135 TEST(AnrTrackerTest, Empty_DoesntCrash) {
136     AnrTracker tracker;
137 
138     ASSERT_TRUE(tracker.empty());
139 
140     ASSERT_EQ(LLONG_MAX, tracker.firstTimeout());
141     // Can't call firstToken() if tracker.empty()
142 }
143 
TEST(AnrTrackerTest,RemoveInvalidItem_DoesntCrash)144 TEST(AnrTrackerTest, RemoveInvalidItem_DoesntCrash) {
145     AnrTracker tracker;
146 
147     tracker.insert(1, nullptr);
148 
149     // Remove with non-matching timestamp
150     tracker.erase(2, nullptr);
151     ASSERT_EQ(1, tracker.firstTimeout());
152     ASSERT_EQ(nullptr, tracker.firstToken());
153 
154     // Remove with non-matching token
155     tracker.erase(1, sp<BBinder>::make());
156     ASSERT_EQ(1, tracker.firstTimeout());
157     ASSERT_EQ(nullptr, tracker.firstToken());
158 
159     // Remove with both non-matching
160     tracker.erase(2, sp<BBinder>::make());
161     ASSERT_EQ(1, tracker.firstTimeout());
162     ASSERT_EQ(nullptr, tracker.firstToken());
163 }
164 
165 } // namespace inputdispatcher
166 
167 } // namespace android
168