1 // Copyright (C) 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <gmock/gmock.h>
16 #include <gtest/gtest.h>
17 #include <stdio.h>
18
19 #include <chrono>
20 #include <thread>
21 #include <vector>
22
23 #include "../metrics/metrics_test_helper.h"
24 #include "src/stats_log_util.h"
25 #include "stats_event.h"
26 #include "tests/statsd_test_util.h"
27
28 #ifdef __ANDROID__
29
30 namespace android {
31 namespace os {
32 namespace statsd {
33
34 using namespace testing;
35 using std::make_shared;
36 using std::shared_ptr;
37 using std::vector;
38 using std::this_thread::sleep_for;
39 using testing::Contains;
40
41 namespace {
42 int pullTagId = 10014;
43
44 bool pullSuccess;
45 vector<std::shared_ptr<LogEvent>> pullData;
46 long pullDelayNs;
47
48 class FakePuller : public StatsPuller {
49 public:
FakePuller()50 FakePuller()
51 : StatsPuller(pullTagId, /*coolDownNs=*/MillisToNano(10), /*timeoutNs=*/MillisToNano(5)){};
52
53 private:
PullInternal(vector<std::shared_ptr<LogEvent>> * data)54 bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override {
55 (*data) = pullData;
56 sleep_for(std::chrono::nanoseconds(pullDelayNs));
57 return pullSuccess;
58 }
59 };
60
61 FakePuller puller;
62
createSimpleEvent(int64_t eventTimeNs,int64_t value)63 std::unique_ptr<LogEvent> createSimpleEvent(int64_t eventTimeNs, int64_t value) {
64 AStatsEvent* statsEvent = AStatsEvent_obtain();
65 AStatsEvent_setAtomId(statsEvent, pullTagId);
66 AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs);
67 AStatsEvent_writeInt64(statsEvent, value);
68
69 std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
70 parseStatsEventToLogEvent(statsEvent, logEvent.get());
71 return logEvent;
72 }
73
74 class StatsPullerTest : public ::testing::Test {
75 public:
StatsPullerTest()76 StatsPullerTest() {
77 }
78
SetUp()79 void SetUp() override {
80 puller.ForceClearCache();
81 pullSuccess = false;
82 pullDelayNs = 0;
83 pullData.clear();
84 }
85 };
86
87 } // Anonymous namespace.
88
TEST_F(StatsPullerTest,PullSuccess)89 TEST_F(StatsPullerTest, PullSuccess) {
90 pullData.push_back(createSimpleEvent(1111L, 33));
91
92 pullSuccess = true;
93
94 vector<std::shared_ptr<LogEvent>> dataHolder;
95 EXPECT_TRUE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
96 ASSERT_EQ(1, dataHolder.size());
97 EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
98 EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
99 ASSERT_EQ(1, dataHolder[0]->size());
100 EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
101
102 sleep_for(std::chrono::milliseconds(11));
103
104 pullData.clear();
105 pullData.push_back(createSimpleEvent(2222L, 44));
106
107 pullSuccess = true;
108
109 EXPECT_TRUE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
110 ASSERT_EQ(1, dataHolder.size());
111 EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
112 EXPECT_EQ(2222L, dataHolder[0]->GetElapsedTimestampNs());
113 ASSERT_EQ(1, dataHolder[0]->size());
114 EXPECT_EQ(44, dataHolder[0]->getValues()[0].mValue.int_value);
115 }
116
TEST_F(StatsPullerTest,PullFailAfterSuccess)117 TEST_F(StatsPullerTest, PullFailAfterSuccess) {
118 pullData.push_back(createSimpleEvent(1111L, 33));
119
120 pullSuccess = true;
121
122 vector<std::shared_ptr<LogEvent>> dataHolder;
123 EXPECT_TRUE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
124 ASSERT_EQ(1, dataHolder.size());
125 EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
126 EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
127 ASSERT_EQ(1, dataHolder[0]->size());
128 EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
129
130 sleep_for(std::chrono::milliseconds(11));
131
132 pullData.clear();
133 pullData.push_back(createSimpleEvent(2222L, 44));
134
135 pullSuccess = false;
136 dataHolder.clear();
137 EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
138 ASSERT_EQ(0, dataHolder.size());
139
140 // Fails due to hitting the cool down.
141 pullSuccess = true;
142 dataHolder.clear();
143 EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
144 ASSERT_EQ(0, dataHolder.size());
145 }
146
147 // Test pull takes longer than timeout, 2nd pull happens shorter than cooldown
TEST_F(StatsPullerTest,PullTakeTooLongAndPullFast)148 TEST_F(StatsPullerTest, PullTakeTooLongAndPullFast) {
149 pullData.push_back(createSimpleEvent(1111L, 33));
150 pullSuccess = true;
151 // timeout is 5ms
152 pullDelayNs = MillisToNano(6);
153
154 vector<std::shared_ptr<LogEvent>> dataHolder;
155 EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
156 ASSERT_EQ(0, dataHolder.size());
157
158 pullData.clear();
159 pullData.push_back(createSimpleEvent(2222L, 44));
160 pullDelayNs = 0;
161
162 pullSuccess = true;
163 dataHolder.clear();
164 EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
165 ASSERT_EQ(0, dataHolder.size());
166 }
167
TEST_F(StatsPullerTest,PullFail)168 TEST_F(StatsPullerTest, PullFail) {
169 pullData.push_back(createSimpleEvent(1111L, 33));
170
171 pullSuccess = false;
172
173 vector<std::shared_ptr<LogEvent>> dataHolder;
174 EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
175 ASSERT_EQ(0, dataHolder.size());
176 }
177
TEST_F(StatsPullerTest,PullTakeTooLong)178 TEST_F(StatsPullerTest, PullTakeTooLong) {
179 pullData.push_back(createSimpleEvent(1111L, 33));
180
181 pullSuccess = true;
182 pullDelayNs = MillisToNano(6);
183
184 vector<std::shared_ptr<LogEvent>> dataHolder;
185 EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
186 ASSERT_EQ(0, dataHolder.size());
187 }
188
TEST_F(StatsPullerTest,PullTooFast)189 TEST_F(StatsPullerTest, PullTooFast) {
190 pullData.push_back(createSimpleEvent(1111L, 33));
191
192 pullSuccess = true;
193
194 vector<std::shared_ptr<LogEvent>> dataHolder;
195 EXPECT_TRUE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
196 ASSERT_EQ(1, dataHolder.size());
197 EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
198 EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
199 ASSERT_EQ(1, dataHolder[0]->size());
200 EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
201
202 pullData.clear();
203 pullData.push_back(createSimpleEvent(2222L, 44));
204
205 pullSuccess = true;
206
207 dataHolder.clear();
208 EXPECT_TRUE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
209 ASSERT_EQ(1, dataHolder.size());
210 EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
211 EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
212 ASSERT_EQ(1, dataHolder[0]->size());
213 EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
214 }
215
TEST_F(StatsPullerTest,PullFailsAndTooFast)216 TEST_F(StatsPullerTest, PullFailsAndTooFast) {
217 pullData.push_back(createSimpleEvent(1111L, 33));
218
219 pullSuccess = false;
220
221 vector<std::shared_ptr<LogEvent>> dataHolder;
222 EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
223 ASSERT_EQ(0, dataHolder.size());
224
225 pullData.clear();
226 pullData.push_back(createSimpleEvent(2222L, 44));
227
228 pullSuccess = true;
229
230 EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
231 ASSERT_EQ(0, dataHolder.size());
232 }
233
TEST_F(StatsPullerTest,PullSameEventTime)234 TEST_F(StatsPullerTest, PullSameEventTime) {
235 pullData.push_back(createSimpleEvent(1111L, 33));
236
237 pullSuccess = true;
238 int64_t eventTimeNs = getElapsedRealtimeNs();
239
240 vector<std::shared_ptr<LogEvent>> dataHolder;
241 EXPECT_TRUE(puller.Pull(eventTimeNs, &dataHolder));
242 ASSERT_EQ(1, dataHolder.size());
243 EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
244 EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
245 ASSERT_EQ(1, dataHolder[0]->size());
246 EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
247
248 pullData.clear();
249 pullData.push_back(createSimpleEvent(2222L, 44));
250
251 // Sleep to ensure the cool down expires.
252 sleep_for(std::chrono::milliseconds(11));
253 pullSuccess = true;
254
255 dataHolder.clear();
256 EXPECT_TRUE(puller.Pull(eventTimeNs, &dataHolder));
257 ASSERT_EQ(1, dataHolder.size());
258 EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
259 EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
260 ASSERT_EQ(1, dataHolder[0]->size());
261 EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
262 }
263
264 // Test pull takes longer than timeout, 2nd pull happens at same event time
TEST_F(StatsPullerTest,PullTakeTooLongAndPullSameEventTime)265 TEST_F(StatsPullerTest, PullTakeTooLongAndPullSameEventTime) {
266 pullData.push_back(createSimpleEvent(1111L, 33));
267 pullSuccess = true;
268 int64_t eventTimeNs = getElapsedRealtimeNs();
269 // timeout is 5ms
270 pullDelayNs = MillisToNano(6);
271
272 vector<std::shared_ptr<LogEvent>> dataHolder;
273 EXPECT_FALSE(puller.Pull(eventTimeNs, &dataHolder));
274 ASSERT_EQ(0, dataHolder.size());
275
276 // Sleep to ensure the cool down expires. 6ms is taken by the delay, so only 5 is needed here.
277 sleep_for(std::chrono::milliseconds(5));
278
279 pullData.clear();
280 pullData.push_back(createSimpleEvent(2222L, 44));
281 pullDelayNs = 0;
282
283 pullSuccess = true;
284 dataHolder.clear();
285 EXPECT_FALSE(puller.Pull(eventTimeNs, &dataHolder));
286 ASSERT_EQ(0, dataHolder.size());
287 }
288
TEST_F(StatsPullerTest,PullFailsAndPullSameEventTime)289 TEST_F(StatsPullerTest, PullFailsAndPullSameEventTime) {
290 pullData.push_back(createSimpleEvent(1111L, 33));
291
292 pullSuccess = false;
293 int64_t eventTimeNs = getElapsedRealtimeNs();
294
295 vector<std::shared_ptr<LogEvent>> dataHolder;
296 EXPECT_FALSE(puller.Pull(eventTimeNs, &dataHolder));
297 ASSERT_EQ(0, dataHolder.size());
298
299 // Sleep to ensure the cool down expires.
300 sleep_for(std::chrono::milliseconds(11));
301
302 pullData.clear();
303 pullData.push_back(createSimpleEvent(2222L, 44));
304
305 pullSuccess = true;
306
307 EXPECT_FALSE(puller.Pull(eventTimeNs, &dataHolder));
308 ASSERT_EQ(0, dataHolder.size());
309 }
310
311 } // namespace statsd
312 } // namespace os
313 } // namespace android
314 #else
315 GTEST_LOG_(INFO) << "This test does nothing.\n";
316 #endif
317