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/logd/LogEvent.h"
16 
17 #include <gtest/gtest.h>
18 
19 #include "frameworks/proto_logging/stats/atoms.pb.h"
20 #include "frameworks/proto_logging/stats/enums/stats/launcher/launcher.pb.h"
21 #include "log/log_event_list.h"
22 #include "stats_event.h"
23 
24 #ifdef __ANDROID__
25 
26 namespace android {
27 namespace os {
28 namespace statsd {
29 
30 using std::string;
31 using std::vector;
32 using util::ProtoOutputStream;
33 using util::ProtoReader;
34 
35 namespace {
36 
37 Field getField(int32_t tag, const vector<int32_t>& pos, int32_t depth, const vector<bool>& last) {
38     Field f(tag, (int32_t*)pos.data(), depth);
39 
40     // For loop starts at 1 because the last field at depth 0 is not decorated.
41     for (int i = 1; i < depth; i++) {
42         if (last[i]) f.decorateLastPos(i);
43     }
44 
45     return f;
46 }
47 
48 void createIntWithBoolAnnotationLogEvent(LogEvent* logEvent, uint8_t annotationId,
49                                          bool annotationValue) {
50     AStatsEvent* statsEvent = AStatsEvent_obtain();
51     AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
52     AStatsEvent_writeInt32(statsEvent, 10);
53     AStatsEvent_addBoolAnnotation(statsEvent, annotationId, annotationValue);
54     AStatsEvent_build(statsEvent);
55 
56     size_t size;
57     uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
58     EXPECT_TRUE(logEvent->parseBuffer(buf, size));
59 
60     AStatsEvent_release(statsEvent);
61 }
62 
63 void createIntWithIntAnnotationLogEvent(LogEvent* logEvent, uint8_t annotationId,
64                                         int annotationValue) {
65     AStatsEvent* statsEvent = AStatsEvent_obtain();
66     AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
67     AStatsEvent_writeInt32(statsEvent, 10);
68     AStatsEvent_addInt32Annotation(statsEvent, annotationId, annotationValue);
69     AStatsEvent_build(statsEvent);
70 
71     size_t size;
72     uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
73     EXPECT_TRUE(logEvent->parseBuffer(buf, size));
74 
75     AStatsEvent_release(statsEvent);
76 }
77 
78 }  // anonymous namespace
79 
80 TEST(LogEventTest, TestPrimitiveParsing) {
81     AStatsEvent* event = AStatsEvent_obtain();
82     AStatsEvent_setAtomId(event, 100);
83     AStatsEvent_writeInt32(event, 10);
84     AStatsEvent_writeInt64(event, 0x123456789);
85     AStatsEvent_writeFloat(event, 2.0);
86     AStatsEvent_writeBool(event, true);
87     AStatsEvent_build(event);
88 
89     size_t size;
90     uint8_t* buf = AStatsEvent_getBuffer(event, &size);
91 
92     LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
93     EXPECT_TRUE(logEvent.parseBuffer(buf, size));
94 
95     EXPECT_EQ(100, logEvent.GetTagId());
96     EXPECT_EQ(1000, logEvent.GetUid());
97     EXPECT_EQ(1001, logEvent.GetPid());
98     EXPECT_FALSE(logEvent.hasAttributionChain());
99 
100     const vector<FieldValue>& values = logEvent.getValues();
101     ASSERT_EQ(4, values.size());
102 
103     const FieldValue& int32Item = values[0];
104     Field expectedField = getField(100, {1, 1, 1}, 0, {false, false, false});
105     EXPECT_EQ(expectedField, int32Item.mField);
106     EXPECT_EQ(Type::INT, int32Item.mValue.getType());
107     EXPECT_EQ(10, int32Item.mValue.int_value);
108 
109     const FieldValue& int64Item = values[1];
110     expectedField = getField(100, {2, 1, 1}, 0, {false, false, false});
111     EXPECT_EQ(expectedField, int64Item.mField);
112     EXPECT_EQ(Type::LONG, int64Item.mValue.getType());
113     EXPECT_EQ(0x123456789, int64Item.mValue.long_value);
114 
115     const FieldValue& floatItem = values[2];
116     expectedField = getField(100, {3, 1, 1}, 0, {false, false, false});
117     EXPECT_EQ(expectedField, floatItem.mField);
118     EXPECT_EQ(Type::FLOAT, floatItem.mValue.getType());
119     EXPECT_EQ(2.0, floatItem.mValue.float_value);
120 
121     const FieldValue& boolItem = values[3];
122     expectedField = getField(100, {4, 1, 1}, 0, {true, false, false});
123     EXPECT_EQ(expectedField, boolItem.mField);
124     EXPECT_EQ(Type::INT, boolItem.mValue.getType());  // FieldValue does not support boolean type
125     EXPECT_EQ(1, boolItem.mValue.int_value);
126 
127     AStatsEvent_release(event);
128 }
129 
130 TEST(LogEventTest, TestStringAndByteArrayParsing) {
131     AStatsEvent* event = AStatsEvent_obtain();
132     AStatsEvent_setAtomId(event, 100);
133     string str = "test";
134     AStatsEvent_writeString(event, str.c_str());
135     AStatsEvent_writeByteArray(event, (uint8_t*)str.c_str(), str.length());
136     AStatsEvent_build(event);
137 
138     size_t size;
139     uint8_t* buf = AStatsEvent_getBuffer(event, &size);
140 
141     LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
142     EXPECT_TRUE(logEvent.parseBuffer(buf, size));
143 
144     EXPECT_EQ(100, logEvent.GetTagId());
145     EXPECT_EQ(1000, logEvent.GetUid());
146     EXPECT_EQ(1001, logEvent.GetPid());
147     EXPECT_FALSE(logEvent.hasAttributionChain());
148 
149     const vector<FieldValue>& values = logEvent.getValues();
150     ASSERT_EQ(2, values.size());
151 
152     const FieldValue& stringItem = values[0];
153     Field expectedField = getField(100, {1, 1, 1}, 0, {false, false, false});
154     EXPECT_EQ(expectedField, stringItem.mField);
155     EXPECT_EQ(Type::STRING, stringItem.mValue.getType());
156     EXPECT_EQ(str, stringItem.mValue.str_value);
157 
158     const FieldValue& storageItem = values[1];
159     expectedField = getField(100, {2, 1, 1}, 0, {true, false, false});
160     EXPECT_EQ(expectedField, storageItem.mField);
161     EXPECT_EQ(Type::STORAGE, storageItem.mValue.getType());
162     vector<uint8_t> expectedValue = {'t', 'e', 's', 't'};
163     EXPECT_EQ(expectedValue, storageItem.mValue.storage_value);
164 
165     AStatsEvent_release(event);
166 }
167 
168 TEST(LogEventTest, TestEmptyString) {
169     AStatsEvent* event = AStatsEvent_obtain();
170     AStatsEvent_setAtomId(event, 100);
171     string empty = "";
172     AStatsEvent_writeString(event, empty.c_str());
173     AStatsEvent_build(event);
174 
175     size_t size;
176     uint8_t* buf = AStatsEvent_getBuffer(event, &size);
177 
178     LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
179     EXPECT_TRUE(logEvent.parseBuffer(buf, size));
180 
181     EXPECT_EQ(100, logEvent.GetTagId());
182     EXPECT_EQ(1000, logEvent.GetUid());
183     EXPECT_EQ(1001, logEvent.GetPid());
184     EXPECT_FALSE(logEvent.hasAttributionChain());
185 
186     const vector<FieldValue>& values = logEvent.getValues();
187     ASSERT_EQ(1, values.size());
188 
189     const FieldValue& item = values[0];
190     Field expectedField = getField(100, {1, 1, 1}, 0, {true, false, false});
191     EXPECT_EQ(expectedField, item.mField);
192     EXPECT_EQ(Type::STRING, item.mValue.getType());
193     EXPECT_EQ(empty, item.mValue.str_value);
194 
195     AStatsEvent_release(event);
196 }
197 
198 TEST(LogEventTest, TestByteArrayWithNullCharacter) {
199     AStatsEvent* event = AStatsEvent_obtain();
200     AStatsEvent_setAtomId(event, 100);
201     uint8_t message[] = {'\t', 'e', '\0', 's', 't'};
202     AStatsEvent_writeByteArray(event, message, 5);
203     AStatsEvent_build(event);
204 
205     size_t size;
206     uint8_t* buf = AStatsEvent_getBuffer(event, &size);
207 
208     LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
209     EXPECT_TRUE(logEvent.parseBuffer(buf, size));
210 
211     EXPECT_EQ(100, logEvent.GetTagId());
212     EXPECT_EQ(1000, logEvent.GetUid());
213     EXPECT_EQ(1001, logEvent.GetPid());
214 
215     const vector<FieldValue>& values = logEvent.getValues();
216     ASSERT_EQ(1, values.size());
217 
218     const FieldValue& item = values[0];
219     Field expectedField = getField(100, {1, 1, 1}, 0, {true, false, false});
220     EXPECT_EQ(expectedField, item.mField);
221     EXPECT_EQ(Type::STORAGE, item.mValue.getType());
222     vector<uint8_t> expectedValue(message, message + 5);
223     EXPECT_EQ(expectedValue, item.mValue.storage_value);
224 
225     AStatsEvent_release(event);
226 }
227 
228 TEST(LogEventTest, TestAttributionChain) {
229     AStatsEvent* event = AStatsEvent_obtain();
230     AStatsEvent_setAtomId(event, 100);
231 
232     string tag1 = "tag1";
233     string tag2 = "tag2";
234 
235     uint32_t uids[] = {1001, 1002};
236     const char* tags[] = {tag1.c_str(), tag2.c_str()};
237 
238     AStatsEvent_writeAttributionChain(event, uids, tags, 2);
239     AStatsEvent_build(event);
240 
241     size_t size;
242     uint8_t* buf = AStatsEvent_getBuffer(event, &size);
243 
244     LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
245     EXPECT_TRUE(logEvent.parseBuffer(buf, size));
246 
247     EXPECT_EQ(100, logEvent.GetTagId());
248     EXPECT_EQ(1000, logEvent.GetUid());
249     EXPECT_EQ(1001, logEvent.GetPid());
250 
251     const vector<FieldValue>& values = logEvent.getValues();
252     ASSERT_EQ(4, values.size());  // 2 per attribution node
253 
254     std::pair<int, int> attrIndexRange;
255     EXPECT_TRUE(logEvent.hasAttributionChain(&attrIndexRange));
256     EXPECT_EQ(0, attrIndexRange.first);
257     EXPECT_EQ(3, attrIndexRange.second);
258 
259     // Check first attribution node
260     const FieldValue& uid1Item = values[0];
261     Field expectedField = getField(100, {1, 1, 1}, 2, {true, false, false});
262     EXPECT_EQ(expectedField, uid1Item.mField);
263     EXPECT_EQ(Type::INT, uid1Item.mValue.getType());
264     EXPECT_EQ(1001, uid1Item.mValue.int_value);
265 
266     const FieldValue& tag1Item = values[1];
267     expectedField = getField(100, {1, 1, 2}, 2, {true, false, true});
268     EXPECT_EQ(expectedField, tag1Item.mField);
269     EXPECT_EQ(Type::STRING, tag1Item.mValue.getType());
270     EXPECT_EQ(tag1, tag1Item.mValue.str_value);
271 
272     // Check second attribution nodes
273     const FieldValue& uid2Item = values[2];
274     expectedField = getField(100, {1, 2, 1}, 2, {true, true, false});
275     EXPECT_EQ(expectedField, uid2Item.mField);
276     EXPECT_EQ(Type::INT, uid2Item.mValue.getType());
277     EXPECT_EQ(1002, uid2Item.mValue.int_value);
278 
279     const FieldValue& tag2Item = values[3];
280     expectedField = getField(100, {1, 2, 2}, 2, {true, true, true});
281     EXPECT_EQ(expectedField, tag2Item.mField);
282     EXPECT_EQ(Type::STRING, tag2Item.mValue.getType());
283     EXPECT_EQ(tag2, tag2Item.mValue.str_value);
284 
285     AStatsEvent_release(event);
286 }
287 
288 TEST(LogEventTest, TestAnnotationIdIsUid) {
289     LogEvent event(/*uid=*/0, /*pid=*/0);
290     createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_IS_UID, true);
291 
292     const vector<FieldValue>& values = event.getValues();
293     ASSERT_EQ(values.size(), 1);
294     EXPECT_EQ(event.getUidFieldIndex(), 0);
295 }
296 
297 TEST(LogEventTest, TestAnnotationIdStateNested) {
298     LogEvent event(/*uid=*/0, /*pid=*/0);
299     createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_STATE_NESTED, true);
300 
301     const vector<FieldValue>& values = event.getValues();
302     ASSERT_EQ(values.size(), 1);
303     EXPECT_TRUE(values[0].mAnnotations.isNested());
304 }
305 
306 TEST(LogEventTest, TestPrimaryFieldAnnotation) {
307     LogEvent event(/*uid=*/0, /*pid=*/0);
308     createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_PRIMARY_FIELD, true);
309 
310     const vector<FieldValue>& values = event.getValues();
311     ASSERT_EQ(values.size(), 1);
312     EXPECT_TRUE(values[0].mAnnotations.isPrimaryField());
313 }
314 
315 TEST(LogEventTest, TestExclusiveStateAnnotation) {
316     LogEvent event(/*uid=*/0, /*pid=*/0);
317     createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_EXCLUSIVE_STATE, true);
318 
319     const vector<FieldValue>& values = event.getValues();
320     ASSERT_EQ(values.size(), 1);
321     EXPECT_TRUE(values[0].mAnnotations.isExclusiveState());
322 }
323 
324 TEST(LogEventTest, TestPrimaryFieldFirstUidAnnotation) {
325     // Event has 10 ints and then an attribution chain
326     int numInts = 10;
327     int firstUidInChainIndex = numInts;
328     string tag1 = "tag1";
329     string tag2 = "tag2";
330     uint32_t uids[] = {1001, 1002};
331     const char* tags[] = {tag1.c_str(), tag2.c_str()};
332 
333     // Construct AStatsEvent
334     AStatsEvent* statsEvent = AStatsEvent_obtain();
335     AStatsEvent_setAtomId(statsEvent, 100);
336     for (int i = 0; i < numInts; i++) {
337         AStatsEvent_writeInt32(statsEvent, 10);
338     }
339     AStatsEvent_writeAttributionChain(statsEvent, uids, tags, 2);
340     AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true);
341     AStatsEvent_build(statsEvent);
342 
343     // Construct LogEvent
344     size_t size;
345     uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
346     LogEvent logEvent(/*uid=*/0, /*pid=*/0);
347     EXPECT_TRUE(logEvent.parseBuffer(buf, size));
348     AStatsEvent_release(statsEvent);
349 
350     // Check annotation
351     const vector<FieldValue>& values = logEvent.getValues();
352     ASSERT_EQ(values.size(), numInts + 4);
353     EXPECT_TRUE(values[firstUidInChainIndex].mAnnotations.isPrimaryField());
354 }
355 
356 TEST(LogEventTest, TestResetStateAnnotation) {
357     int32_t resetState = 10;
358     LogEvent event(/*uid=*/0, /*pid=*/0);
359     createIntWithIntAnnotationLogEvent(&event, ANNOTATION_ID_TRIGGER_STATE_RESET, resetState);
360 
361     const vector<FieldValue>& values = event.getValues();
362     ASSERT_EQ(values.size(), 1);
363     EXPECT_EQ(event.getResetState(), resetState);
364 }
365 
366 TEST(LogEventTest, TestExclusiveStateAnnotationAfterTooManyFields) {
367     AStatsEvent* event = AStatsEvent_obtain();
368     AStatsEvent_setAtomId(event, 100);
369 
370     const unsigned int numAttributionNodes = 64;
371 
372     uint32_t uids[numAttributionNodes];
373     const char* tags[numAttributionNodes];
374 
375     for (unsigned int i = 1; i <= numAttributionNodes; i++) {
376         uids[i-1] = i;
377         tags[i-1] = std::to_string(i).c_str();
378     }
379 
380     AStatsEvent_writeAttributionChain(event, uids, tags, numAttributionNodes);
381     AStatsEvent_writeInt32(event, 1);
382     AStatsEvent_addBoolAnnotation(event, ANNOTATION_ID_EXCLUSIVE_STATE, true);
383 
384     AStatsEvent_build(event);
385 
386     size_t size;
387     uint8_t* buf = AStatsEvent_getBuffer(event, &size);
388 
389     LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
390     EXPECT_FALSE(logEvent.parseBuffer(buf, size));
391     EXPECT_EQ(-1, logEvent.getExclusiveStateFieldIndex());
392 
393     AStatsEvent_release(event);
394 }
395 
396 TEST(LogEventTest, TestUidAnnotationAfterTooManyFields) {
397     AStatsEvent* event = AStatsEvent_obtain();
398     AStatsEvent_setAtomId(event, 100);
399 
400     const unsigned int numAttributionNodes = 64;
401 
402     uint32_t uids[numAttributionNodes];
403     const char* tags[numAttributionNodes];
404 
405     for (unsigned int i = 1; i <= numAttributionNodes; i++) {
406         uids[i-1] = i;
407         tags[i-1] = std::to_string(i).c_str();
408     }
409 
410     AStatsEvent_writeAttributionChain(event, uids, tags, numAttributionNodes);
411     AStatsEvent_writeInt32(event, 1);
412     AStatsEvent_addBoolAnnotation(event, ANNOTATION_ID_IS_UID, true);
413 
414     AStatsEvent_build(event);
415 
416     size_t size;
417     uint8_t* buf = AStatsEvent_getBuffer(event, &size);
418 
419     LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
420     EXPECT_FALSE(logEvent.parseBuffer(buf, size));
421     EXPECT_EQ(-1, logEvent.getUidFieldIndex());
422 
423     AStatsEvent_release(event);
424 }
425 
426 TEST(LogEventTest, TestAttributionChainEndIndexAfterTooManyFields) {
427     AStatsEvent* event = AStatsEvent_obtain();
428     AStatsEvent_setAtomId(event, 100);
429 
430     const unsigned int numAttributionNodes = 65;
431 
432     uint32_t uids[numAttributionNodes];
433     const char* tags[numAttributionNodes];
434 
435     for (unsigned int i = 1; i <= numAttributionNodes; i++) {
436         uids[i-1] = i;
437         tags[i-1] = std::to_string(i).c_str();
438     }
439 
440     AStatsEvent_writeAttributionChain(event, uids, tags, numAttributionNodes);
441 
442     AStatsEvent_build(event);
443 
444     size_t size;
445     uint8_t* buf = AStatsEvent_getBuffer(event, &size);
446 
447     LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
448     EXPECT_FALSE(logEvent.parseBuffer(buf, size));
449     EXPECT_FALSE(logEvent.hasAttributionChain());
450 
451     AStatsEvent_release(event);
452 }
453 
454 TEST(LogEventTest, TestEmptyAttributionChainWithPrimaryFieldFirstUidAnnotation) {
455     AStatsEvent* event = AStatsEvent_obtain();
456     AStatsEvent_setAtomId(event, 100);
457 
458     uint32_t uids[] = {};
459     const char* tags[] = {};
460 
461     AStatsEvent_writeInt32(event, 10);
462     AStatsEvent_writeAttributionChain(event, uids, tags, 0);
463     AStatsEvent_addBoolAnnotation(event, ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true);
464 
465     AStatsEvent_build(event);
466 
467     size_t size;
468     uint8_t* buf = AStatsEvent_getBuffer(event, &size);
469 
470     LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
471     EXPECT_FALSE(logEvent.parseBuffer(buf, size));
472 
473     AStatsEvent_release(event);
474 }
475 
476 }  // namespace statsd
477 }  // namespace os
478 }  // namespace android
479 #else
480 GTEST_LOG_(INFO) << "This test does nothing.\n";
481 #endif
482