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