1 // Copyright (C) 2017 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 "src/condition/SimpleConditionTracker.h"
16 #include "tests/statsd_test_util.h"
17
18 #include <gmock/gmock.h>
19 #include <gtest/gtest.h>
20 #include <stdio.h>
21 #include <vector>
22 #include <numeric>
23
24 using std::map;
25 using std::unordered_map;
26 using std::vector;
27
28 #ifdef __ANDROID__
29
30 namespace android {
31 namespace os {
32 namespace statsd {
33
34 const ConfigKey kConfigKey(0, 12345);
35
36 const int ATTRIBUTION_NODE_FIELD_ID = 1;
37 const int ATTRIBUTION_UID_FIELD_ID = 1;
38 const int TAG_ID = 1;
39
getWakeLockHeldCondition(bool countNesting,bool defaultFalse,bool outputSlicedUid,Position position)40 SimplePredicate getWakeLockHeldCondition(bool countNesting, bool defaultFalse,
41 bool outputSlicedUid, Position position) {
42 SimplePredicate simplePredicate;
43 simplePredicate.set_start(StringToId("WAKE_LOCK_ACQUIRE"));
44 simplePredicate.set_stop(StringToId("WAKE_LOCK_RELEASE"));
45 simplePredicate.set_stop_all(StringToId("RELEASE_ALL"));
46 if (outputSlicedUid) {
47 simplePredicate.mutable_dimensions()->set_field(TAG_ID);
48 simplePredicate.mutable_dimensions()->add_child()->set_field(ATTRIBUTION_NODE_FIELD_ID);
49 simplePredicate.mutable_dimensions()->mutable_child(0)->set_position(position);
50 simplePredicate.mutable_dimensions()->mutable_child(0)->add_child()->set_field(
51 ATTRIBUTION_UID_FIELD_ID);
52 }
53
54 simplePredicate.set_count_nesting(countNesting);
55 simplePredicate.set_initial_value(defaultFalse ? SimplePredicate_InitialValue_FALSE
56 : SimplePredicate_InitialValue_UNKNOWN);
57 return simplePredicate;
58 }
59
writeAttributionNodesToEvent(LogEvent * event,const std::vector<int> & uids)60 void writeAttributionNodesToEvent(LogEvent* event, const std::vector<int> &uids) {
61 std::vector<AttributionNodeInternal> nodes;
62 for (size_t i = 0; i < uids.size(); ++i) {
63 AttributionNodeInternal node;
64 node.set_uid(uids[i]);
65 nodes.push_back(node);
66 }
67 event->write(nodes); // attribution chain.
68 }
69
makeWakeLockEvent(LogEvent * event,const std::vector<int> & uids,const string & wl,int acquire)70 void makeWakeLockEvent(
71 LogEvent* event, const std::vector<int> &uids, const string& wl, int acquire) {
72 writeAttributionNodesToEvent(event, uids);
73 event->write(wl);
74 event->write(acquire);
75 event->init();
76 }
77
getWakeLockQueryKey(const Position position,const std::vector<int> & uids,const string & conditionName)78 std::map<int64_t, HashableDimensionKey> getWakeLockQueryKey(
79 const Position position,
80 const std::vector<int> &uids, const string& conditionName) {
81 std::map<int64_t, HashableDimensionKey> outputKeyMap;
82 std::vector<int> uid_indexes;
83 int pos[] = {1, 1, 1};
84 int depth = 2;
85 Field field(1, pos, depth);
86 switch(position) {
87 case Position::FIRST:
88 uid_indexes.push_back(0);
89 break;
90 case Position::LAST:
91 uid_indexes.push_back(uids.size() - 1);
92 field.setField(0x02018001);
93 break;
94 case Position::ANY:
95 uid_indexes.resize(uids.size());
96 std::iota(uid_indexes.begin(), uid_indexes.end(), 0);
97 field.setField(0x02010001);
98 break;
99 default:
100 break;
101 }
102
103 for (const int idx : uid_indexes) {
104 Value value((int32_t)uids[idx]);
105 HashableDimensionKey dim;
106 dim.addValue(FieldValue(field, value));
107 outputKeyMap[StringToId(conditionName)] = dim;
108 }
109 return outputKeyMap;
110 }
111
TEST(SimpleConditionTrackerTest,TestNonSlicedCondition)112 TEST(SimpleConditionTrackerTest, TestNonSlicedCondition) {
113 SimplePredicate simplePredicate;
114 simplePredicate.set_start(StringToId("SCREEN_TURNED_ON"));
115 simplePredicate.set_stop(StringToId("SCREEN_TURNED_OFF"));
116 simplePredicate.set_count_nesting(false);
117 simplePredicate.set_initial_value(SimplePredicate_InitialValue_UNKNOWN);
118
119 unordered_map<int64_t, int> trackerNameIndexMap;
120 trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
121 trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
122
123 SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), 0 /*tracker index*/,
124 simplePredicate, trackerNameIndexMap);
125 EXPECT_FALSE(conditionTracker.isSliced());
126
127 LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
128
129 vector<MatchingState> matcherState;
130 matcherState.push_back(MatchingState::kNotMatched);
131 matcherState.push_back(MatchingState::kNotMatched);
132
133 vector<sp<ConditionTracker>> allPredicates;
134 vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
135 vector<bool> changedCache(1, false);
136
137 conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
138 changedCache);
139 // not matched start or stop. condition doesn't change
140 EXPECT_EQ(ConditionState::kUnknown, conditionCache[0]);
141 EXPECT_FALSE(changedCache[0]);
142
143 // prepare a case for match start.
144 matcherState.clear();
145 matcherState.push_back(MatchingState::kMatched);
146 matcherState.push_back(MatchingState::kNotMatched);
147 conditionCache[0] = ConditionState::kNotEvaluated;
148 changedCache[0] = false;
149
150 conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
151 changedCache);
152 // now condition should change to true.
153 EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
154 EXPECT_TRUE(changedCache[0]);
155
156 // match nothing.
157 matcherState.clear();
158 matcherState.push_back(MatchingState::kNotMatched);
159 matcherState.push_back(MatchingState::kNotMatched);
160 conditionCache[0] = ConditionState::kNotEvaluated;
161 changedCache[0] = false;
162
163 conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
164 changedCache);
165 EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
166 EXPECT_FALSE(changedCache[0]);
167
168 // the case for match stop.
169 matcherState.clear();
170 matcherState.push_back(MatchingState::kNotMatched);
171 matcherState.push_back(MatchingState::kMatched);
172 conditionCache[0] = ConditionState::kNotEvaluated;
173 changedCache[0] = false;
174
175 conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
176 changedCache);
177
178 // condition changes to false.
179 EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
180 EXPECT_TRUE(changedCache[0]);
181
182 // match stop again.
183 matcherState.clear();
184 matcherState.push_back(MatchingState::kNotMatched);
185 matcherState.push_back(MatchingState::kMatched);
186 conditionCache[0] = ConditionState::kNotEvaluated;
187 changedCache[0] = false;
188
189 conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
190 changedCache);
191 // condition should still be false. not changed.
192 EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
193 EXPECT_FALSE(changedCache[0]);
194 }
195
TEST(SimpleConditionTrackerTest,TestNonSlicedConditionNestCounting)196 TEST(SimpleConditionTrackerTest, TestNonSlicedConditionNestCounting) {
197 std::vector<sp<ConditionTracker>> allConditions;
198 SimplePredicate simplePredicate;
199 simplePredicate.set_start(StringToId("SCREEN_TURNED_ON"));
200 simplePredicate.set_stop(StringToId("SCREEN_TURNED_OFF"));
201 simplePredicate.set_count_nesting(true);
202
203 unordered_map<int64_t, int> trackerNameIndexMap;
204 trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
205 trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
206
207 SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"),
208 0 /*condition tracker index*/, simplePredicate,
209 trackerNameIndexMap);
210 EXPECT_FALSE(conditionTracker.isSliced());
211
212 LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
213
214 // one matched start
215 vector<MatchingState> matcherState;
216 matcherState.push_back(MatchingState::kMatched);
217 matcherState.push_back(MatchingState::kNotMatched);
218 vector<sp<ConditionTracker>> allPredicates;
219 vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
220 vector<bool> changedCache(1, false);
221
222 conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
223 changedCache);
224
225 EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
226 EXPECT_TRUE(changedCache[0]);
227
228 // prepare for another matched start.
229 matcherState.clear();
230 matcherState.push_back(MatchingState::kMatched);
231 matcherState.push_back(MatchingState::kNotMatched);
232 conditionCache[0] = ConditionState::kNotEvaluated;
233 changedCache[0] = false;
234
235 conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
236 changedCache);
237
238 EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
239 EXPECT_FALSE(changedCache[0]);
240
241 // ONE MATCHED STOP
242 matcherState.clear();
243 matcherState.push_back(MatchingState::kNotMatched);
244 matcherState.push_back(MatchingState::kMatched);
245 conditionCache[0] = ConditionState::kNotEvaluated;
246 changedCache[0] = false;
247
248 conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
249 changedCache);
250 // result should still be true
251 EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
252 EXPECT_FALSE(changedCache[0]);
253
254 // ANOTHER MATCHED STOP
255 matcherState.clear();
256 matcherState.push_back(MatchingState::kNotMatched);
257 matcherState.push_back(MatchingState::kMatched);
258 conditionCache[0] = ConditionState::kNotEvaluated;
259 changedCache[0] = false;
260
261 conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
262 changedCache);
263 EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
264 EXPECT_TRUE(changedCache[0]);
265 }
266
TEST(SimpleConditionTrackerTest,TestSlicedCondition)267 TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
268 std::vector<sp<ConditionTracker>> allConditions;
269 for (Position position :
270 { Position::FIRST, Position::LAST}) {
271 vector<Matcher> dimensionInCondition;
272 std::unordered_set<HashableDimensionKey> dimensionKeys;
273
274 SimplePredicate simplePredicate = getWakeLockHeldCondition(
275 true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
276 position);
277 string conditionName = "WL_HELD_BY_UID2";
278
279 unordered_map<int64_t, int> trackerNameIndexMap;
280 trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
281 trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
282 trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
283
284 SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
285 0 /*condition tracker index*/, simplePredicate,
286 trackerNameIndexMap);
287
288 std::vector<int> uids = {111, 222, 333};
289
290 LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
291 makeWakeLockEvent(&event, uids, "wl1", 1);
292
293 // one matched start
294 vector<MatchingState> matcherState;
295 matcherState.push_back(MatchingState::kMatched);
296 matcherState.push_back(MatchingState::kNotMatched);
297 matcherState.push_back(MatchingState::kNotMatched);
298 vector<sp<ConditionTracker>> allPredicates;
299 vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
300 vector<bool> changedCache(1, false);
301
302 conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
303 changedCache);
304
305 if (position == Position::FIRST ||
306 position == Position::LAST) {
307 EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
308 } else {
309 EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
310 }
311 EXPECT_TRUE(changedCache[0]);
312 if (position == Position::FIRST ||
313 position == Position::LAST) {
314 EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), 1u);
315 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
316 } else {
317 EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), uids.size());
318 }
319
320 // Now test query
321 const auto queryKey = getWakeLockQueryKey(position, uids, conditionName);
322 conditionCache[0] = ConditionState::kNotEvaluated;
323
324 conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
325 false, false,
326 conditionCache, dimensionKeys);
327 EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
328
329 // another wake lock acquired by this uid
330 LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
331 makeWakeLockEvent(&event2, uids, "wl2", 1);
332 matcherState.clear();
333 matcherState.push_back(MatchingState::kMatched);
334 matcherState.push_back(MatchingState::kNotMatched);
335 conditionCache[0] = ConditionState::kNotEvaluated;
336 changedCache[0] = false;
337 conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
338 changedCache);
339 EXPECT_FALSE(changedCache[0]);
340 if (position == Position::FIRST ||
341 position == Position::LAST) {
342 EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
343 } else {
344 EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
345 }
346 EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
347 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
348
349
350 // wake lock 1 release
351 LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
352 makeWakeLockEvent(&event3, uids, "wl1", 0); // now release it.
353 matcherState.clear();
354 matcherState.push_back(MatchingState::kNotMatched);
355 matcherState.push_back(MatchingState::kMatched);
356 conditionCache[0] = ConditionState::kNotEvaluated;
357 changedCache[0] = false;
358 conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
359 changedCache);
360 // nothing changes, because wake lock 2 is still held for this uid
361 EXPECT_FALSE(changedCache[0]);
362 if (position == Position::FIRST ||
363 position == Position::LAST) {
364 EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
365 } else {
366 EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
367 }
368 EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
369 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
370
371 LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
372 makeWakeLockEvent(&event4, uids, "wl2", 0); // now release it.
373 matcherState.clear();
374 matcherState.push_back(MatchingState::kNotMatched);
375 matcherState.push_back(MatchingState::kMatched);
376 conditionCache[0] = ConditionState::kNotEvaluated;
377 changedCache[0] = false;
378 conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
379 changedCache);
380 EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
381 EXPECT_TRUE(changedCache[0]);
382 if (position == Position::FIRST ||
383 position == Position::LAST) {
384 EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), 1u);
385 EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
386 } else {
387 EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), uids.size());
388 }
389
390 // query again
391 conditionCache[0] = ConditionState::kNotEvaluated;
392 conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
393 false, false,
394 conditionCache, dimensionKeys);
395 EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
396 }
397
398 }
399
TEST(SimpleConditionTrackerTest,TestSlicedWithNoOutputDim)400 TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
401 std::vector<sp<ConditionTracker>> allConditions;
402 vector<Matcher> dimensionInCondition;
403 std::unordered_set<HashableDimensionKey> dimensionKeys;
404
405 SimplePredicate simplePredicate = getWakeLockHeldCondition(
406 true /*nesting*/, true /*default to false*/, false /*slice output by uid*/,
407 Position::ANY /* position */);
408 string conditionName = "WL_HELD";
409
410 unordered_map<int64_t, int> trackerNameIndexMap;
411 trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
412 trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
413 trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
414
415 SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
416 0 /*condition tracker index*/, simplePredicate,
417 trackerNameIndexMap);
418
419 EXPECT_FALSE(conditionTracker.isSliced());
420
421 std::vector<int> uid_list1 = {111, 1111, 11111};
422 string uid1_wl1 = "wl1_1";
423 std::vector<int> uid_list2 = {222, 2222, 22222};
424 string uid2_wl1 = "wl2_1";
425
426 LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
427 makeWakeLockEvent(&event, uid_list1, uid1_wl1, 1);
428
429 // one matched start for uid1
430 vector<MatchingState> matcherState;
431 matcherState.push_back(MatchingState::kMatched);
432 matcherState.push_back(MatchingState::kNotMatched);
433 matcherState.push_back(MatchingState::kNotMatched);
434 vector<sp<ConditionTracker>> allPredicates;
435 vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
436 vector<bool> changedCache(1, false);
437
438 conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
439 changedCache);
440
441 EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
442 EXPECT_TRUE(changedCache[0]);
443
444 // Now test query
445 ConditionKey queryKey;
446 conditionCache[0] = ConditionState::kNotEvaluated;
447
448 conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
449 true, true,
450 conditionCache, dimensionKeys);
451 EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
452
453 // another wake lock acquired by this uid
454 LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
455 makeWakeLockEvent(&event2, uid_list2, uid2_wl1, 1);
456 matcherState.clear();
457 matcherState.push_back(MatchingState::kMatched);
458 matcherState.push_back(MatchingState::kNotMatched);
459 conditionCache[0] = ConditionState::kNotEvaluated;
460 changedCache[0] = false;
461 conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
462 changedCache);
463 EXPECT_FALSE(changedCache[0]);
464
465 // uid1 wake lock 1 release
466 LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
467 makeWakeLockEvent(&event3, uid_list1, uid1_wl1, 0); // now release it.
468 matcherState.clear();
469 matcherState.push_back(MatchingState::kNotMatched);
470 matcherState.push_back(MatchingState::kMatched);
471 conditionCache[0] = ConditionState::kNotEvaluated;
472 changedCache[0] = false;
473 conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
474 changedCache);
475 // nothing changes, because uid2 is still holding wl.
476 EXPECT_FALSE(changedCache[0]);
477
478 LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
479 makeWakeLockEvent(&event4, uid_list2, uid2_wl1, 0); // now release it.
480 matcherState.clear();
481 matcherState.push_back(MatchingState::kNotMatched);
482 matcherState.push_back(MatchingState::kMatched);
483 conditionCache[0] = ConditionState::kNotEvaluated;
484 changedCache[0] = false;
485 conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
486 changedCache);
487 EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
488 EXPECT_TRUE(changedCache[0]);
489
490 // query again
491 conditionCache[0] = ConditionState::kNotEvaluated;
492 dimensionKeys.clear();
493 conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
494 true, true,
495 conditionCache, dimensionKeys);
496 EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
497 }
498
TEST(SimpleConditionTrackerTest,TestStopAll)499 TEST(SimpleConditionTrackerTest, TestStopAll) {
500 std::vector<sp<ConditionTracker>> allConditions;
501 for (Position position :
502 { Position::FIRST, Position::LAST }) {
503 vector<Matcher> dimensionInCondition;
504 std::unordered_set<HashableDimensionKey> dimensionKeys;
505 SimplePredicate simplePredicate = getWakeLockHeldCondition(
506 true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
507 position);
508 string conditionName = "WL_HELD_BY_UID3";
509
510 unordered_map<int64_t, int> trackerNameIndexMap;
511 trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
512 trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
513 trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
514
515 SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
516 0 /*condition tracker index*/, simplePredicate,
517 trackerNameIndexMap);
518
519 std::vector<int> uid_list1 = {111, 1111, 11111};
520 std::vector<int> uid_list2 = {222, 2222, 22222};
521
522 LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
523 makeWakeLockEvent(&event, uid_list1, "wl1", 1);
524
525 // one matched start
526 vector<MatchingState> matcherState;
527 matcherState.push_back(MatchingState::kMatched);
528 matcherState.push_back(MatchingState::kNotMatched);
529 matcherState.push_back(MatchingState::kNotMatched);
530 vector<sp<ConditionTracker>> allPredicates;
531 vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
532 vector<bool> changedCache(1, false);
533
534 conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
535 changedCache);
536 if (position == Position::FIRST ||
537 position == Position::LAST) {
538 EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
539 } else {
540 EXPECT_EQ(uid_list1.size(), conditionTracker.mSlicedConditionState.size());
541 }
542 EXPECT_TRUE(changedCache[0]);
543 {
544 if (position == Position::FIRST ||
545 position == Position::LAST) {
546 EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
547 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
548 } else {
549 EXPECT_EQ(uid_list1.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
550 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
551 }
552 }
553
554 // Now test query
555 const auto queryKey = getWakeLockQueryKey(position, uid_list1, conditionName);
556 conditionCache[0] = ConditionState::kNotEvaluated;
557
558 conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
559 false, false,
560 conditionCache, dimensionKeys);
561 EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
562
563 // another wake lock acquired by uid2
564 LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
565 makeWakeLockEvent(&event2, uid_list2, "wl2", 1);
566 matcherState.clear();
567 matcherState.push_back(MatchingState::kMatched);
568 matcherState.push_back(MatchingState::kNotMatched);
569 matcherState.push_back(MatchingState::kNotMatched);
570 conditionCache[0] = ConditionState::kNotEvaluated;
571 changedCache[0] = false;
572 conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
573 changedCache);
574 if (position == Position::FIRST ||
575 position == Position::LAST) {
576 EXPECT_EQ(2UL, conditionTracker.mSlicedConditionState.size());
577 } else {
578 EXPECT_EQ(uid_list1.size() + uid_list2.size(),
579 conditionTracker.mSlicedConditionState.size());
580 }
581 EXPECT_TRUE(changedCache[0]);
582 {
583 if (position == Position::FIRST ||
584 position == Position::LAST) {
585 EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
586 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
587 } else {
588 EXPECT_EQ(uid_list2.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
589 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
590 }
591 }
592
593
594 // TEST QUERY
595 const auto queryKey2 = getWakeLockQueryKey(position, uid_list2, conditionName);
596 conditionCache[0] = ConditionState::kNotEvaluated;
597 conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
598 false, false,
599 conditionCache, dimensionKeys);
600
601 EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
602
603
604 // stop all event
605 LogEvent event3(2 /*tagId*/, 0 /*timestamp*/);
606 matcherState.clear();
607 matcherState.push_back(MatchingState::kNotMatched);
608 matcherState.push_back(MatchingState::kNotMatched);
609 matcherState.push_back(MatchingState::kMatched);
610
611 conditionCache[0] = ConditionState::kNotEvaluated;
612 changedCache[0] = false;
613 conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
614 changedCache);
615 EXPECT_TRUE(changedCache[0]);
616 EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
617 {
618 if (position == Position::FIRST || position == Position::LAST) {
619 EXPECT_EQ(2UL, conditionTracker.getChangedToFalseDimensions(allConditions)->size());
620 EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
621 } else {
622 EXPECT_EQ(uid_list1.size() + uid_list2.size(),
623 conditionTracker.getChangedToFalseDimensions(allConditions)->size());
624 EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
625 }
626 }
627
628 // TEST QUERY
629 const auto queryKey3 = getWakeLockQueryKey(position, uid_list1, conditionName);
630 conditionCache[0] = ConditionState::kNotEvaluated;
631 conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
632 false, false,
633 conditionCache, dimensionKeys);
634 EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
635
636 // TEST QUERY
637 const auto queryKey4 = getWakeLockQueryKey(position, uid_list2, conditionName);
638 conditionCache[0] = ConditionState::kNotEvaluated;
639 conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
640 false, false,
641 conditionCache, dimensionKeys);
642 EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
643 }
644 }
645
646 } // namespace statsd
647 } // namespace os
648 } // namespace android
649 #else
650 GTEST_LOG_(INFO) << "This test does nothing.\n";
651 #endif
652