1 //
2 // Copyright (C) 2015 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 "shill/net/event_history.h"
18
19 #include <gtest/gtest.h>
20
21 #include <memory>
22 #include <string>
23 #include <vector>
24
25 #include "shill/net/mock_time.h"
26 #include "shill/net/shill_time.h"
27
28 using std::deque;
29 using std::string;
30 using std::vector;
31 using ::testing::Mock;
32 using ::testing::Return;
33
34 namespace shill {
35
36 namespace {
37 // consts here
38 } // namespace
39
40 class EventHistoryTest : public ::testing::Test {
41 public:
EventHistoryTest()42 EventHistoryTest() : event_history_(new EventHistory()) {
43 event_history_->time_ = &time_;
44 }
45
~EventHistoryTest()46 virtual ~EventHistoryTest() {}
47
SetMaxEventsSaved(int num_events)48 void SetMaxEventsSaved(int num_events) {
49 event_history_->max_events_saved_ = num_events;
50 event_history_->max_events_specified_ = true;
51 }
52
SetNoMaxEvents()53 void SetNoMaxEvents() {
54 event_history_->max_events_saved_ = 0;
55 event_history_->max_events_specified_ = false;
56 }
57
GetMaxEventsSaved()58 int GetMaxEventsSaved() { return event_history_->max_events_saved_; }
59
GetMaxEventsSpecified()60 bool GetMaxEventsSpecified() { return event_history_->max_events_specified_; }
61
GetEvents()62 deque<Timestamp>* GetEvents() { return &event_history_->events_; }
63
RecordEvent(Timestamp now)64 void RecordEvent(Timestamp now) {
65 EXPECT_CALL(time_, GetNow()).WillOnce(Return(now));
66 event_history_->RecordEvent();
67 }
68
ExpireEventsBefore(int seconds_ago,Timestamp now,EventHistory::ClockType clock_type)69 void ExpireEventsBefore(int seconds_ago, Timestamp now,
70 EventHistory::ClockType clock_type) {
71 EXPECT_CALL(time_, GetNow()).WillOnce(Return(now));
72 event_history_->ExpireEventsBefore(seconds_ago, clock_type);
73 }
74
RecordEventAndExpireEventsBefore(int seconds_ago,Timestamp now,EventHistory::ClockType clock_type)75 void RecordEventAndExpireEventsBefore(int seconds_ago, Timestamp now,
76 EventHistory::ClockType clock_type) {
77 EXPECT_CALL(time_, GetNow()).WillOnce(Return(now));
78 event_history_->RecordEventAndExpireEventsBefore(seconds_ago, clock_type);
79 }
80
ExtractWallClockToStrings()81 vector<string> ExtractWallClockToStrings() {
82 return event_history_->ExtractWallClockToStrings();
83 }
84
GetTimestamp(int monotonic_seconds,int boottime_seconds,const string & wall_clock)85 Timestamp GetTimestamp(int monotonic_seconds, int boottime_seconds,
86 const string& wall_clock) {
87 struct timeval monotonic = {.tv_sec = monotonic_seconds, .tv_usec = 0};
88 struct timeval boottime = {.tv_sec = boottime_seconds, .tv_usec = 0};
89 return Timestamp(monotonic, boottime, wall_clock);
90 }
91
CountEventsWithinInterval(int seconds_ago,EventHistory::ClockType clock_type,Timestamp now)92 int CountEventsWithinInterval(int seconds_ago,
93 EventHistory::ClockType clock_type,
94 Timestamp now) {
95 EXPECT_CALL(time_, GetNow()).WillOnce(Return(now));
96 return event_history_->CountEventsWithinInterval(seconds_ago, clock_type);
97 }
98
99 protected:
100 MockTime time_;
101 std::unique_ptr<EventHistory> event_history_;
102 };
103
TEST_F(EventHistoryTest,RecordEvent)104 TEST_F(EventHistoryTest, RecordEvent) {
105 const int kTime1 = 5;
106 const int kTime2 = 8;
107 EXPECT_TRUE(GetEvents()->empty());
108 RecordEvent(GetTimestamp(kTime1, kTime1, ""));
109 EXPECT_EQ(1, GetEvents()->size());
110 EXPECT_EQ(kTime1, GetEvents()->back().monotonic.tv_sec);
111 EXPECT_EQ(kTime1, GetEvents()->back().boottime.tv_sec);
112
113 // Latest events pushed to the back of the list.
114 RecordEvent(GetTimestamp(kTime2, kTime2, ""));
115 EXPECT_EQ(2, GetEvents()->size());
116 EXPECT_EQ(kTime2, GetEvents()->back().monotonic.tv_sec);
117 EXPECT_EQ(kTime2, GetEvents()->back().boottime.tv_sec);
118 }
119
TEST_F(EventHistoryTest,EventThresholdReached)120 TEST_F(EventHistoryTest, EventThresholdReached) {
121 const int kMaxEventsThreshold = 10;
122 const int kTime1 = 5;
123 const int kTime2 = 8;
124 SetMaxEventsSaved(kMaxEventsThreshold);
125 EXPECT_TRUE(GetEvents()->empty());
126 for (int i = 0; i < kMaxEventsThreshold; ++i) {
127 RecordEvent(GetTimestamp(kTime1, kTime1, ""));
128 }
129 // All kMaxEventsThreshold events successfully saved.
130 EXPECT_EQ(kMaxEventsThreshold, GetEvents()->size());
131 EXPECT_EQ(kTime1, GetEvents()->back().monotonic.tv_sec);
132 EXPECT_EQ(kTime1, GetEvents()->back().boottime.tv_sec);
133
134 // One timestamp will be evicted to make way for the latest event timestamp,
135 // which will be pushed to the back of the list.
136 RecordEvent(GetTimestamp(kTime2, kTime2, ""));
137 EXPECT_EQ(kMaxEventsThreshold, GetEvents()->size());
138 EXPECT_EQ(kTime2, GetEvents()->back().monotonic.tv_sec);
139 EXPECT_EQ(kTime2, GetEvents()->back().boottime.tv_sec);
140 }
141
TEST_F(EventHistoryTest,ExpireEventsBefore_EvictExpiredEvents)142 TEST_F(EventHistoryTest, ExpireEventsBefore_EvictExpiredEvents) {
143 const int kExpiryThresholdSeconds = 10;
144 const int kTimeEarly = 5;
145 const int kTimeLate = kTimeEarly + kExpiryThresholdSeconds + 1;
146 const int kNumEarlierEvents = 20;
147
148 EXPECT_TRUE(GetEvents()->empty());
149 for (int i = 0; i < kNumEarlierEvents; ++i) {
150 RecordEvent(GetTimestamp(kTimeEarly, kTimeEarly, ""));
151 }
152 EXPECT_EQ(kNumEarlierEvents, GetEvents()->size());
153 EXPECT_EQ(kTimeEarly, GetEvents()->front().monotonic.tv_sec);
154 EXPECT_EQ(kTimeEarly, GetEvents()->front().boottime.tv_sec);
155
156 RecordEvent(GetTimestamp(kTimeLate, kTimeLate, ""));
157 EXPECT_EQ(kNumEarlierEvents + 1, GetEvents()->size());
158 EXPECT_EQ(kTimeEarly, GetEvents()->front().monotonic.tv_sec);
159 EXPECT_EQ(kTimeEarly, GetEvents()->front().boottime.tv_sec);
160 EXPECT_EQ(kTimeLate, GetEvents()->back().monotonic.tv_sec);
161 EXPECT_EQ(kTimeLate, GetEvents()->back().boottime.tv_sec);
162
163 // Expect that all the kTimeEarly event timestamps will be evicted since
164 // they took place more than kExpiryThresholdSeconds ago.
165 ExpireEventsBefore(kExpiryThresholdSeconds,
166 GetTimestamp(kTimeLate, kTimeLate, ""),
167 EventHistory::kClockTypeBoottime);
168 EXPECT_EQ(1, GetEvents()->size());
169 EXPECT_EQ(kTimeLate, GetEvents()->front().monotonic.tv_sec);
170 EXPECT_EQ(kTimeLate, GetEvents()->front().boottime.tv_sec);
171 }
172
TEST_F(EventHistoryTest,ExpireEventsBefore_UseSuspendTime)173 TEST_F(EventHistoryTest, ExpireEventsBefore_UseSuspendTime) {
174 const int kExpiryThresholdSeconds = 10;
175 const int kTime1 = 5;
176
177 EventHistory::ClockType clock_type;
178
179 EXPECT_TRUE(GetEvents()->empty());
180 RecordEvent(GetTimestamp(kTime1, kTime1, ""));
181 EXPECT_EQ(1, GetEvents()->size());
182 EXPECT_EQ(kTime1, GetEvents()->front().monotonic.tv_sec);
183 EXPECT_EQ(kTime1, GetEvents()->front().boottime.tv_sec);
184
185 const int kTime2Monotonic = kTime1 + kExpiryThresholdSeconds - 1;
186 const int kTime2Boot = kTime1 + kExpiryThresholdSeconds + 1;
187 // If we don't count suspend time (i.e. use the monotonic clock), we will not
188 // expire the event because it took place less than kExpiryThresholdSeconds
189 // ago.
190 clock_type = EventHistory::kClockTypeMonotonic;
191 ExpireEventsBefore(kExpiryThresholdSeconds,
192 GetTimestamp(kTime2Monotonic, kTime2Boot, ""), clock_type);
193 EXPECT_EQ(1, GetEvents()->size());
194
195 // If we count suspend time (i.e. use the boottime clock), we will expire the
196 // event because it took place more than kExpiryThresholdSeconds ago.
197 clock_type = EventHistory::kClockTypeBoottime;
198 ExpireEventsBefore(kExpiryThresholdSeconds,
199 GetTimestamp(kTime2Monotonic, kTime2Boot, ""), clock_type);
200 EXPECT_TRUE(GetEvents()->empty());
201 }
202
TEST_F(EventHistoryTest,RecordEventAndExpireEventsBefore)203 TEST_F(EventHistoryTest, RecordEventAndExpireEventsBefore) {
204 const int kExpiryThresholdSeconds = 10;
205 const int kTimeEarly = 5;
206 const int kTimeLate = kTimeEarly + kExpiryThresholdSeconds + 1;
207 const int kNumEarlierEvents = 20;
208 const int kMaxEventsThreshold = kNumEarlierEvents / 2;
209
210 SetMaxEventsSaved(kMaxEventsThreshold);
211 EXPECT_TRUE(GetEvents()->empty());
212 for (int i = 0; i < kNumEarlierEvents; ++i) {
213 RecordEventAndExpireEventsBefore(kExpiryThresholdSeconds,
214 GetTimestamp(kTimeEarly, kTimeEarly, ""),
215 EventHistory::kClockTypeBoottime);
216 }
217 // kNumEarlierEvents is greater than kMaxEventsThreshold, so only
218 // kMaxEventsThreshold events should be saved.
219 EXPECT_EQ(kMaxEventsThreshold, GetEvents()->size());
220 EXPECT_EQ(kTimeEarly, GetEvents()->front().monotonic.tv_sec);
221 EXPECT_EQ(kTimeEarly, GetEvents()->front().boottime.tv_sec);
222
223 // Expect that the kTimeLate timestamp should be added and all the kTimeEarly
224 // event timestamps will be evicted since the the former took place less than
225 // kExpiryThresholdSeconds ago and the latter took place more than
226 // kExpiryThresholdSeconds ago.
227 RecordEventAndExpireEventsBefore(kExpiryThresholdSeconds,
228 GetTimestamp(kTimeLate, kTimeLate, ""),
229 EventHistory::kClockTypeBoottime);
230 EXPECT_EQ(1, GetEvents()->size());
231 EXPECT_EQ(kTimeLate, GetEvents()->front().monotonic.tv_sec);
232 EXPECT_EQ(kTimeLate, GetEvents()->front().boottime.tv_sec);
233 }
234
TEST_F(EventHistoryTest,ConvertTimestampsToStrings)235 TEST_F(EventHistoryTest, ConvertTimestampsToStrings) {
236 EXPECT_TRUE(ExtractWallClockToStrings().empty());
237
238 const Timestamp kValues[] = {
239 GetTimestamp(123, 123, "2012-12-09T12:41:22.123456+0100"),
240 GetTimestamp(234, 234, "2012-12-31T23:59:59.012345+0100")};
241 for (size_t i = 0; i < arraysize(kValues); ++i) {
242 RecordEvent(kValues[i]);
243 }
244
245 vector<string> strings = ExtractWallClockToStrings();
246 EXPECT_GT(arraysize(kValues), 0);
247 ASSERT_EQ(arraysize(kValues), strings.size());
248 for (size_t i = 0; i < arraysize(kValues); i++) {
249 EXPECT_EQ(kValues[i].wall_clock, strings[i]);
250 }
251 }
252
TEST_F(EventHistoryTest,CountEventsWithinInterval)253 TEST_F(EventHistoryTest, CountEventsWithinInterval) {
254 const int kExpiryThresholdSeconds = 10;
255 const int kTimeEarly = 5;
256 const int kTimeLate = kTimeEarly + kExpiryThresholdSeconds + 1;
257 const int kNumEarlierEvents = 20;
258 const int kNumLaterEvents = 10;
259 const int kMaxEventsThreshold = kNumEarlierEvents + kNumLaterEvents;
260
261 SetMaxEventsSaved(kMaxEventsThreshold);
262 EXPECT_TRUE(GetEvents()->empty());
263 for (int i = 0; i < kNumEarlierEvents; ++i) {
264 RecordEvent(GetTimestamp(kTimeEarly, kTimeEarly, ""));
265 }
266 for (int i = 0; i < kNumLaterEvents; ++i) {
267 RecordEvent(GetTimestamp(kTimeLate, kTimeLate, ""));
268 }
269 EXPECT_EQ(kMaxEventsThreshold, GetEvents()->size());
270
271 // Only count later events.
272 EXPECT_EQ(kNumLaterEvents,
273 CountEventsWithinInterval(kExpiryThresholdSeconds,
274 EventHistory::kClockTypeBoottime,
275 GetTimestamp(kTimeLate, kTimeLate, "")));
276
277 // Count all events.
278 EXPECT_EQ(
279 kMaxEventsThreshold,
280 CountEventsWithinInterval(kTimeLate, EventHistory::kClockTypeBoottime,
281 GetTimestamp(kTimeLate, kTimeLate, "")));
282 }
283
284 } // namespace shill
285