1 /*
2  * Copyright (C) 2019 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 "stats_event.h"
18 #include <gtest/gtest.h>
19 #include <utils/SystemClock.h>
20 
21 // Keep in sync with stats_event.c. Consider moving to separate header file to avoid duplication.
22 /* ERRORS */
23 #define ERROR_NO_TIMESTAMP 0x1
24 #define ERROR_NO_ATOM_ID 0x2
25 #define ERROR_OVERFLOW 0x4
26 #define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8
27 #define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10
28 #define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20
29 #define ERROR_INVALID_ANNOTATION_ID 0x40
30 #define ERROR_ANNOTATION_ID_TOO_LARGE 0x80
31 #define ERROR_TOO_MANY_ANNOTATIONS 0x100
32 #define ERROR_TOO_MANY_FIELDS 0x200
33 #define ERROR_INVALID_VALUE_TYPE 0x400
34 #define ERROR_STRING_NOT_NULL_TERMINATED 0x800
35 #define ERROR_ATOM_ID_INVALID_POSITION 0x2000
36 #define ERROR_LIST_TOO_LONG 0x4000
37 
38 /* TYPE IDS */
39 #define INT32_TYPE 0x00
40 #define INT64_TYPE 0x01
41 #define STRING_TYPE 0x02
42 #define LIST_TYPE 0x03
43 #define FLOAT_TYPE 0x04
44 #define BOOL_TYPE 0x05
45 #define BYTE_ARRAY_TYPE 0x06
46 #define OBJECT_TYPE 0x07
47 #define KEY_VALUE_PAIRS_TYPE 0x08
48 #define ATTRIBUTION_CHAIN_TYPE 0x09
49 #define ERROR_TYPE 0x0F
50 
51 using std::string;
52 using std::vector;
53 
54 // Side-effect: this function moves the start of the buffer past the read value
55 template <class T>
readNext(uint8_t ** buffer)56 T readNext(uint8_t** buffer) {
57     T value;
58     if ((reinterpret_cast<uintptr_t>(*buffer) % alignof(T)) == 0) {
59         value = *(T*)(*buffer);
60     } else {
61         memcpy(&value, *buffer, sizeof(T));
62     }
63     *buffer += sizeof(T);
64     return value;
65 }
66 
checkTypeHeader(uint8_t ** buffer,uint8_t typeId,uint8_t numAnnotations=0)67 void checkTypeHeader(uint8_t** buffer, uint8_t typeId, uint8_t numAnnotations = 0) {
68     uint8_t typeHeader = (numAnnotations << 4) | typeId;
69     EXPECT_EQ(readNext<uint8_t>(buffer), typeHeader);
70 }
71 
72 template <class T>
checkScalar(uint8_t ** buffer,T expectedValue)73 void checkScalar(uint8_t** buffer, T expectedValue) {
74     EXPECT_EQ(readNext<T>(buffer), expectedValue);
75 }
76 
checkString(uint8_t ** buffer,const string & expectedString)77 void checkString(uint8_t** buffer, const string& expectedString) {
78     uint32_t size = readNext<uint32_t>(buffer);
79     string parsedString((char*)(*buffer), size);
80     EXPECT_EQ(parsedString, expectedString);
81     *buffer += size;  // move buffer past string we just read
82 }
83 
checkByteArray(uint8_t ** buffer,const vector<uint8_t> & expectedByteArray)84 void checkByteArray(uint8_t** buffer, const vector<uint8_t>& expectedByteArray) {
85     uint32_t size = readNext<uint32_t>(buffer);
86     vector<uint8_t> parsedByteArray(*buffer, *buffer + size);
87     EXPECT_EQ(parsedByteArray, expectedByteArray);
88     *buffer += size;  // move buffer past byte array we just read
89 }
90 
checkArrayMetadata(uint8_t ** buffer,uint8_t numElements,uint8_t elementTypeId,uint8_t numAnnotations=0)91 void checkArrayMetadata(uint8_t** buffer, uint8_t numElements, uint8_t elementTypeId,
92                         uint8_t numAnnotations = 0) {
93     checkTypeHeader(buffer, LIST_TYPE, numAnnotations);
94     EXPECT_EQ(readNext<uint8_t>(buffer), numElements);
95     checkTypeHeader(buffer, elementTypeId);
96 }
97 
98 template <class T>
checkScalarArray(uint8_t ** buffer,uint8_t numElements,uint8_t elementTypeId,const T * expectedArrayValues,uint8_t numAnnotations=0)99 void checkScalarArray(uint8_t** buffer, uint8_t numElements, uint8_t elementTypeId,
100                       const T* expectedArrayValues, uint8_t numAnnotations = 0) {
101     checkArrayMetadata(buffer, numElements, elementTypeId, numAnnotations);
102 
103     for (int i = 0; i < numElements; i++) {
104         checkScalar(buffer, expectedArrayValues[i]);
105     }
106 }
107 
108 template <class T>
checkAnnotation(uint8_t ** buffer,uint8_t annotationId,uint8_t typeId,T annotationValue)109 void checkAnnotation(uint8_t** buffer, uint8_t annotationId, uint8_t typeId, T annotationValue) {
110     EXPECT_EQ(readNext<uint8_t>(buffer), annotationId);
111     EXPECT_EQ(readNext<uint8_t>(buffer), typeId);
112     checkScalar<T>(buffer, annotationValue);
113 }
114 
checkMetadata(uint8_t ** buffer,uint8_t numElements,int64_t startTime,int64_t endTime,uint32_t atomId,uint8_t numAtomLevelAnnotations=0)115 void checkMetadata(uint8_t** buffer, uint8_t numElements, int64_t startTime, int64_t endTime,
116                    uint32_t atomId, uint8_t numAtomLevelAnnotations = 0) {
117     // All events start with OBJECT_TYPE id.
118     checkTypeHeader(buffer, OBJECT_TYPE);
119 
120     // We increment by 2 because the number of elements listed in the
121     // serialization accounts for the timestamp and atom id as well.
122     checkScalar(buffer, static_cast<uint8_t>(numElements + 2));
123 
124     // Check timestamp
125     checkTypeHeader(buffer, INT64_TYPE);
126     int64_t timestamp = readNext<int64_t>(buffer);
127     EXPECT_GE(timestamp, startTime);
128     EXPECT_LE(timestamp, endTime);
129 
130     // Check atom id
131     checkTypeHeader(buffer, INT32_TYPE, numAtomLevelAnnotations);
132     checkScalar(buffer, atomId);
133 }
134 
TEST(StatsEventTest,TestScalars)135 TEST(StatsEventTest, TestScalars) {
136     uint32_t atomId = 100;
137     int32_t int32Value = -5;
138     int64_t int64Value = -2 * android::elapsedRealtimeNano();
139     float floatValue = 2.0;
140     bool boolValue = false;
141 
142     int64_t startTime = android::elapsedRealtimeNano();
143     AStatsEvent* event = AStatsEvent_obtain();
144     AStatsEvent_setAtomId(event, atomId);
145     AStatsEvent_writeInt32(event, int32Value);
146     AStatsEvent_writeInt64(event, int64Value);
147     AStatsEvent_writeFloat(event, floatValue);
148     AStatsEvent_writeBool(event, boolValue);
149     AStatsEvent_build(event);
150     int64_t endTime = android::elapsedRealtimeNano();
151 
152     size_t bufferSize;
153     uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
154     uint8_t* bufferEnd = buffer + bufferSize;
155 
156     checkMetadata(&buffer, /*numElements=*/4, startTime, endTime, atomId);
157 
158     // check int32 element
159     checkTypeHeader(&buffer, INT32_TYPE);
160     checkScalar(&buffer, int32Value);
161 
162     // check int64 element
163     checkTypeHeader(&buffer, INT64_TYPE);
164     checkScalar(&buffer, int64Value);
165 
166     // check float element
167     checkTypeHeader(&buffer, FLOAT_TYPE);
168     checkScalar(&buffer, floatValue);
169 
170     // check bool element
171     checkTypeHeader(&buffer, BOOL_TYPE);
172     checkScalar(&buffer, boolValue);
173 
174     EXPECT_EQ(buffer, bufferEnd);  // ensure that we have read the entire buffer
175     EXPECT_EQ(AStatsEvent_getErrors(event), 0);
176     AStatsEvent_release(event);
177 }
178 
TEST(StatsEventTest,TestStrings)179 TEST(StatsEventTest, TestStrings) {
180     uint32_t atomId = 100;
181     string str = "test_string";
182 
183     int64_t startTime = android::elapsedRealtimeNano();
184     AStatsEvent* event = AStatsEvent_obtain();
185     AStatsEvent_setAtomId(event, atomId);
186     AStatsEvent_writeString(event, str.c_str());
187     AStatsEvent_build(event);
188     int64_t endTime = android::elapsedRealtimeNano();
189 
190     size_t bufferSize;
191     uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
192     uint8_t* bufferEnd = buffer + bufferSize;
193 
194     checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
195 
196     checkTypeHeader(&buffer, STRING_TYPE);
197     checkString(&buffer, str);
198 
199     EXPECT_EQ(buffer, bufferEnd);  // ensure that we have read the entire buffer
200     EXPECT_EQ(AStatsEvent_getErrors(event), 0);
201     AStatsEvent_release(event);
202 }
203 
TEST(StatsEventTest,TestNullString)204 TEST(StatsEventTest, TestNullString) {
205     uint32_t atomId = 100;
206     char* str = nullptr;
207 
208     int64_t startTime = android::elapsedRealtimeNano();
209     AStatsEvent* event = AStatsEvent_obtain();
210     AStatsEvent_setAtomId(event, atomId);
211     AStatsEvent_writeString(event, str);
212     AStatsEvent_build(event);
213     int64_t endTime = android::elapsedRealtimeNano();
214 
215     size_t bufferSize;
216     uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
217     uint8_t* bufferEnd = buffer + bufferSize;
218 
219     checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
220 
221     checkTypeHeader(&buffer, STRING_TYPE);
222     checkString(&buffer, "");
223 
224     EXPECT_EQ(buffer, bufferEnd);  // ensure that we have read the entire buffer
225     EXPECT_EQ(AStatsEvent_getErrors(event), 0);
226     AStatsEvent_release(event);
227 }
228 
TEST(StatsEventTest,TestByteArrays)229 TEST(StatsEventTest, TestByteArrays) {
230     uint32_t atomId = 100;
231     vector<uint8_t> message = {'b', 'y', 't', '\0', 'e', 's'};
232 
233     int64_t startTime = android::elapsedRealtimeNano();
234     AStatsEvent* event = AStatsEvent_obtain();
235     AStatsEvent_setAtomId(event, atomId);
236     AStatsEvent_writeByteArray(event, message.data(), message.size());
237     AStatsEvent_build(event);
238     int64_t endTime = android::elapsedRealtimeNano();
239 
240     size_t bufferSize;
241     uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
242     uint8_t* bufferEnd = buffer + bufferSize;
243 
244     checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
245 
246     checkTypeHeader(&buffer, BYTE_ARRAY_TYPE);
247     checkByteArray(&buffer, message);
248 
249     EXPECT_EQ(buffer, bufferEnd);  // ensure that we have read the entire buffer
250     EXPECT_EQ(AStatsEvent_getErrors(event), 0);
251     AStatsEvent_release(event);
252 }
253 
TEST(StatsEventTest,TestNullByteArrays)254 TEST(StatsEventTest, TestNullByteArrays) {
255     uint32_t atomId = 100;
256     uint8_t* buf = nullptr;
257     vector<uint8_t> message;
258 
259     int64_t startTime = android::elapsedRealtimeNano();
260     AStatsEvent* event = AStatsEvent_obtain();
261     AStatsEvent_setAtomId(event, atomId);
262     AStatsEvent_writeByteArray(event, buf, 2);
263     AStatsEvent_build(event);
264     int64_t endTime = android::elapsedRealtimeNano();
265 
266     size_t bufferSize;
267     uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
268     uint8_t* bufferEnd = buffer + bufferSize;
269 
270     checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
271 
272     checkTypeHeader(&buffer, BYTE_ARRAY_TYPE);
273     checkByteArray(&buffer, message);
274 
275     EXPECT_EQ(buffer, bufferEnd);  // ensure that we have read the entire buffer
276     EXPECT_EQ(AStatsEvent_getErrors(event), 0);
277     AStatsEvent_release(event);
278 }
279 
TEST(StatsEventTest,TestAllArrays)280 TEST(StatsEventTest, TestAllArrays) {
281     uint32_t atomId = 100;
282 
283     uint8_t numElements = 3;
284     int32_t int32Array[3] = {3, 6, 9};
285     int64_t int64Array[3] = {1000L, 1001L, 1002L};
286     float floatArray[3] = {0.1f, 0.3f, 0.09f};
287     bool boolArray[3] = {0, 1, 1};
288 
289     vector<string> stringArray = {"str1", "str2", "str3"};
290     const char* cStringArray[3];
291     for (int i = 0; i < numElements; i++) {
292         cStringArray[i] = stringArray[i].c_str();
293     }
294 
295     int64_t startTime = android::elapsedRealtimeNano();
296     AStatsEvent* event = AStatsEvent_obtain();
297     AStatsEvent_setAtomId(event, atomId);
298     AStatsEvent_writeInt32Array(event, int32Array, numElements);
299     AStatsEvent_writeInt64Array(event, int64Array, numElements);
300     AStatsEvent_writeFloatArray(event, floatArray, numElements);
301     AStatsEvent_writeBoolArray(event, boolArray, numElements);
302     AStatsEvent_writeStringArray(event, cStringArray, numElements);
303     AStatsEvent_build(event);
304     int64_t endTime = android::elapsedRealtimeNano();
305 
306     size_t bufferSize;
307     uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
308     uint8_t* bufferEnd = buffer + bufferSize;
309 
310     checkMetadata(&buffer, /*numTopLevelElements=*/5, startTime, endTime, atomId);
311 
312     // check int32Array element
313     checkScalarArray(&buffer, numElements, INT32_TYPE, int32Array);
314 
315     // check int64Array element
316     checkScalarArray(&buffer, numElements, INT64_TYPE, int64Array);
317 
318     // check floatArray element
319     checkScalarArray(&buffer, numElements, FLOAT_TYPE, floatArray);
320 
321     // check boolArray element
322     checkScalarArray(&buffer, numElements, BOOL_TYPE, boolArray);
323 
324     // check stringArray element
325     checkArrayMetadata(&buffer, numElements, STRING_TYPE);
326     for (int i = 0; i < numElements; i++) {
327         checkString(&buffer, stringArray[i]);
328     }
329 
330     EXPECT_EQ(buffer, bufferEnd);  // ensure that we have read the entire buffer
331     EXPECT_EQ(AStatsEvent_getErrors(event), 0);
332     AStatsEvent_release(event);
333 }
334 
TEST(StatsEventTest,TestAttributionChains)335 TEST(StatsEventTest, TestAttributionChains) {
336     uint32_t atomId = 100;
337 
338     uint8_t numNodes = 50;
339     uint32_t uids[numNodes];
340     vector<string> tags(numNodes);  // storage that cTag elements point to
341     const char* cTags[numNodes];
342     for (int i = 0; i < (int)numNodes; i++) {
343         uids[i] = i;
344         if (0 == i) {
345             tags.push_back("");
346             cTags[i] = nullptr;
347         } else {
348             tags.push_back("test" + std::to_string(i));
349             cTags[i] = tags[i].c_str();
350         }
351     }
352 
353     int64_t startTime = android::elapsedRealtimeNano();
354     AStatsEvent* event = AStatsEvent_obtain();
355     AStatsEvent_setAtomId(event, atomId);
356     AStatsEvent_writeAttributionChain(event, uids, cTags, numNodes);
357     AStatsEvent_build(event);
358     int64_t endTime = android::elapsedRealtimeNano();
359 
360     size_t bufferSize;
361     uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
362     uint8_t* bufferEnd = buffer + bufferSize;
363 
364     checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
365 
366     checkTypeHeader(&buffer, ATTRIBUTION_CHAIN_TYPE);
367     checkScalar(&buffer, numNodes);
368     for (int i = 0; i < numNodes; i++) {
369         checkScalar(&buffer, uids[i]);
370         checkString(&buffer, tags[i]);
371     }
372 
373     EXPECT_EQ(buffer, bufferEnd);  // ensure that we have read the entire buffer
374     EXPECT_EQ(AStatsEvent_getErrors(event), 0);
375     AStatsEvent_release(event);
376 }
377 
TEST(StatsEventTest,TestFieldAnnotations)378 TEST(StatsEventTest, TestFieldAnnotations) {
379     uint32_t atomId = 100;
380 
381     // first element information
382     bool boolValue = false;
383     uint8_t boolAnnotation1Id = 1;
384     uint8_t boolAnnotation2Id = 2;
385     bool boolAnnotation1Value = true;
386     int32_t boolAnnotation2Value = 3;
387 
388     // second element information
389     float floatValue = -5.0;
390     uint8_t floatAnnotation1Id = 3;
391     uint8_t floatAnnotation2Id = 4;
392     int32_t floatAnnotation1Value = 8;
393     bool floatAnnotation2Value = false;
394 
395     int64_t startTime = android::elapsedRealtimeNano();
396     AStatsEvent* event = AStatsEvent_obtain();
397     AStatsEvent_setAtomId(event, atomId);
398     AStatsEvent_writeBool(event, boolValue);
399     AStatsEvent_addBoolAnnotation(event, boolAnnotation1Id, boolAnnotation1Value);
400     AStatsEvent_addInt32Annotation(event, boolAnnotation2Id, boolAnnotation2Value);
401     AStatsEvent_writeFloat(event, floatValue);
402     AStatsEvent_addInt32Annotation(event, floatAnnotation1Id, floatAnnotation1Value);
403     AStatsEvent_addBoolAnnotation(event, floatAnnotation2Id, floatAnnotation2Value);
404     AStatsEvent_build(event);
405     int64_t endTime = android::elapsedRealtimeNano();
406 
407     size_t bufferSize;
408     uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
409     uint8_t* bufferEnd = buffer + bufferSize;
410 
411     checkMetadata(&buffer, /*numElements=*/2, startTime, endTime, atomId);
412 
413     // check first element
414     checkTypeHeader(&buffer, BOOL_TYPE, /*numAnnotations=*/2);
415     checkScalar(&buffer, boolValue);
416     checkAnnotation(&buffer, boolAnnotation1Id, BOOL_TYPE, boolAnnotation1Value);
417     checkAnnotation(&buffer, boolAnnotation2Id, INT32_TYPE, boolAnnotation2Value);
418 
419     // check second element
420     checkTypeHeader(&buffer, FLOAT_TYPE, /*numAnnotations=*/2);
421     checkScalar(&buffer, floatValue);
422     checkAnnotation(&buffer, floatAnnotation1Id, INT32_TYPE, floatAnnotation1Value);
423     checkAnnotation(&buffer, floatAnnotation2Id, BOOL_TYPE, floatAnnotation2Value);
424 
425     EXPECT_EQ(buffer, bufferEnd);  // ensure that we have read the entire buffer
426     EXPECT_EQ(AStatsEvent_getErrors(event), 0);
427     AStatsEvent_release(event);
428 }
429 
TEST(StatsEventTest,TestArrayFieldAnnotations)430 TEST(StatsEventTest, TestArrayFieldAnnotations) {
431     uint32_t atomId = 100;
432 
433     // array annotation info
434     uint8_t boolAnnotationId = 1;
435     uint8_t int32AnnotationId = 2;
436     bool boolAnnotationValue = true;
437     int32_t int32AnnotationValue = 4;
438 
439     uint8_t numElements = 3;
440     int32_t int32Array[3] = {3, 6, 9};
441 
442     int64_t startTime = android::elapsedRealtimeNano();
443     AStatsEvent* event = AStatsEvent_obtain();
444     AStatsEvent_setAtomId(event, atomId);
445     AStatsEvent_writeInt32Array(event, int32Array, numElements);
446     AStatsEvent_addBoolAnnotation(event, boolAnnotationId, boolAnnotationValue);
447     AStatsEvent_addInt32Annotation(event, int32AnnotationId, int32AnnotationValue);
448     AStatsEvent_build(event);
449     int64_t endTime = android::elapsedRealtimeNano();
450 
451     size_t bufferSize;
452     uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
453     uint8_t* bufferEnd = buffer + bufferSize;
454 
455     checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
456 
457     // check first element
458     checkScalarArray(&buffer, numElements, INT32_TYPE, int32Array, /*numAnnotations=*/2);
459     checkAnnotation(&buffer, boolAnnotationId, BOOL_TYPE, boolAnnotationValue);
460     checkAnnotation(&buffer, int32AnnotationId, INT32_TYPE, int32AnnotationValue);
461 
462     EXPECT_EQ(buffer, bufferEnd);  // ensure that we have read the entire buffer
463     EXPECT_EQ(AStatsEvent_getErrors(event), 0);
464     AStatsEvent_release(event);
465 }
466 
TEST(StatsEventTest,TestAtomLevelAnnotations)467 TEST(StatsEventTest, TestAtomLevelAnnotations) {
468     uint32_t atomId = 100;
469     // atom-level annotation information
470     uint8_t boolAnnotationId = 1;
471     uint8_t int32AnnotationId = 2;
472     bool boolAnnotationValue = false;
473     int32_t int32AnnotationValue = 5;
474 
475     float fieldValue = -3.5;
476 
477     int64_t startTime = android::elapsedRealtimeNano();
478     AStatsEvent* event = AStatsEvent_obtain();
479     AStatsEvent_setAtomId(event, atomId);
480     AStatsEvent_addBoolAnnotation(event, boolAnnotationId, boolAnnotationValue);
481     AStatsEvent_addInt32Annotation(event, int32AnnotationId, int32AnnotationValue);
482     AStatsEvent_writeFloat(event, fieldValue);
483     AStatsEvent_build(event);
484     int64_t endTime = android::elapsedRealtimeNano();
485 
486     size_t bufferSize;
487     uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
488     uint8_t* bufferEnd = buffer + bufferSize;
489 
490     checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId,
491                   /*numAtomLevelAnnotations=*/2);
492 
493     // check atom-level annotations
494     checkAnnotation(&buffer, boolAnnotationId, BOOL_TYPE, boolAnnotationValue);
495     checkAnnotation(&buffer, int32AnnotationId, INT32_TYPE, int32AnnotationValue);
496 
497     // check first element
498     checkTypeHeader(&buffer, FLOAT_TYPE);
499     checkScalar(&buffer, fieldValue);
500 
501     EXPECT_EQ(buffer, bufferEnd);  // ensure that we have read the entire buffer
502     EXPECT_EQ(AStatsEvent_getErrors(event), 0);
503     AStatsEvent_release(event);
504 }
505 
TEST(StatsEventTest,TestNoAtomIdError)506 TEST(StatsEventTest, TestNoAtomIdError) {
507     AStatsEvent* event = AStatsEvent_obtain();
508     // Don't set the atom id in order to trigger the error.
509     AStatsEvent_build(event);
510 
511     uint32_t errors = AStatsEvent_getErrors(event);
512     EXPECT_EQ(errors & ERROR_NO_ATOM_ID, ERROR_NO_ATOM_ID);
513 
514     AStatsEvent_release(event);
515 }
516 
TEST(StatsEventTest,TestPushOverflowError)517 TEST(StatsEventTest, TestPushOverflowError) {
518     const char* str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
519     const int writeCount = 120;  // Number of times to write str in the event.
520 
521     AStatsEvent* event = AStatsEvent_obtain();
522     AStatsEvent_setAtomId(event, 100);
523 
524     // Add str to the event 120 times. Each str takes >35 bytes so this will
525     // overflow the 4068 byte buffer.
526     // We want to keep writeCount less than 127 to avoid hitting
527     // ERROR_TOO_MANY_FIELDS.
528     for (int i = 0; i < writeCount; i++) {
529         AStatsEvent_writeString(event, str);
530     }
531     AStatsEvent_write(event);
532 
533     uint32_t errors = AStatsEvent_getErrors(event);
534     EXPECT_EQ(errors & ERROR_OVERFLOW, ERROR_OVERFLOW);
535 
536     AStatsEvent_release(event);
537 }
538 
TEST(StatsEventTest,TestHeapBufferOverflowError)539 TEST(StatsEventTest, TestHeapBufferOverflowError) {
540     const std::string testString(4039, 'A');
541     const std::string testString2(47135, 'B');
542 
543     AStatsEvent* event = AStatsEvent_obtain();
544     AStatsEvent_setAtomId(event, 100);
545 
546     AStatsEvent_writeString(event, testString.c_str());
547     size_t bufferSize = 0;
548     AStatsEvent_getBuffer(event, &bufferSize);
549     EXPECT_EQ(bufferSize, 4060);
550     uint32_t errors = AStatsEvent_getErrors(event);
551     EXPECT_EQ(errors, 0);
552 
553     // expand the buffer and fill with data up to the very last byte
554     AStatsEvent_writeString(event, testString2.c_str());
555     bufferSize = 0;
556     AStatsEvent_getBuffer(event, &bufferSize);
557     EXPECT_EQ(bufferSize, 50 * 1024);
558 
559     errors = AStatsEvent_getErrors(event);
560     EXPECT_EQ(errors, 0);
561 
562     // this write is no-op due to buffer reached its max capacity
563     // should set the overflow flag
564     AStatsEvent_writeString(event, testString2.c_str());
565     bufferSize = 0;
566     AStatsEvent_getBuffer(event, &bufferSize);
567     EXPECT_EQ(bufferSize, 50 * 1024);
568 
569     errors = AStatsEvent_getErrors(event);
570     EXPECT_EQ(errors & ERROR_OVERFLOW, ERROR_OVERFLOW);
571 
572     // here should be crash
573     AStatsEvent_addBoolAnnotation(event, 1, false);
574 
575     AStatsEvent_write(event);
576 
577     errors = AStatsEvent_getErrors(event);
578     EXPECT_EQ(errors & ERROR_OVERFLOW, ERROR_OVERFLOW);
579 
580     AStatsEvent_release(event);
581 }
582 
TEST(StatsEventTest,TestPullOverflowError)583 TEST(StatsEventTest, TestPullOverflowError) {
584     const uint32_t atomId = 10100;
585     const vector<uint8_t> bytes(430 /* number of elements */, 1 /* value of each element */);
586     const int writeCount = 120;  // Number of times to write bytes in the event.
587 
588     AStatsEvent* event = AStatsEvent_obtain();
589     AStatsEvent_setAtomId(event, atomId);
590 
591     // Add bytes to the event 120 times. Size of bytes is 430 so this will
592     // overflow the 50 KB pulled event buffer.
593     // We want to keep writeCount less than 127 to avoid hitting
594     // ERROR_TOO_MANY_FIELDS.
595     for (int i = 0; i < writeCount; i++) {
596         AStatsEvent_writeByteArray(event, bytes.data(), bytes.size());
597     }
598     AStatsEvent_build(event);
599 
600     uint32_t errors = AStatsEvent_getErrors(event);
601     EXPECT_EQ(errors & ERROR_OVERFLOW, ERROR_OVERFLOW);
602 
603     AStatsEvent_release(event);
604 }
605 
TEST(StatsEventTest,TestLargePull)606 TEST(StatsEventTest, TestLargePull) {
607     const uint32_t atomId = 100;
608     const string str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
609     const int writeCount = 120;  // Number of times to write str in the event.
610     const int64_t startTime = android::elapsedRealtimeNano();
611 
612     AStatsEvent* event = AStatsEvent_obtain();
613     AStatsEvent_setAtomId(event, atomId);
614 
615     // Add str to the event 120 times.
616     // We want to keep writeCount less than 127 to avoid hitting
617     // ERROR_TOO_MANY_FIELDS.
618     for (int i = 0; i < writeCount; i++) {
619         AStatsEvent_writeString(event, str.c_str());
620     }
621     AStatsEvent_build(event);
622     int64_t endTime = android::elapsedRealtimeNano();
623 
624     size_t bufferSize;
625     uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
626     uint8_t* bufferEnd = buffer + bufferSize;
627 
628     checkMetadata(&buffer, writeCount, startTime, endTime, atomId);
629 
630     // Check all instances of str have been written.
631     for (int i = 0; i < writeCount; i++) {
632         checkTypeHeader(&buffer, STRING_TYPE);
633         checkString(&buffer, str);
634     }
635 
636     EXPECT_EQ(buffer, bufferEnd);  // Ensure that we have read the entire buffer.
637     EXPECT_EQ(AStatsEvent_getErrors(event), 0);
638     AStatsEvent_release(event);
639 }
640 
TEST(StatsEventTest,TestAtomIdInvalidPositionError)641 TEST(StatsEventTest, TestAtomIdInvalidPositionError) {
642     AStatsEvent* event = AStatsEvent_obtain();
643     AStatsEvent_writeInt32(event, 0);
644     AStatsEvent_setAtomId(event, 100);
645     AStatsEvent_writeBool(event, true);
646     AStatsEvent_build(event);
647 
648     uint32_t errors = AStatsEvent_getErrors(event);
649     EXPECT_EQ(errors & ERROR_ATOM_ID_INVALID_POSITION, ERROR_ATOM_ID_INVALID_POSITION);
650 
651     AStatsEvent_release(event);
652 }
653 
TEST(StatsEventTest,TestOverwriteTimestamp)654 TEST(StatsEventTest, TestOverwriteTimestamp) {
655     uint32_t atomId = 100;
656     int64_t expectedTimestamp = 0x123456789;
657     AStatsEvent* event = AStatsEvent_obtain();
658     AStatsEvent_setAtomId(event, atomId);
659     AStatsEvent_overwriteTimestamp(event, expectedTimestamp);
660     AStatsEvent_build(event);
661 
662     uint8_t* buffer = AStatsEvent_getBuffer(event, NULL);
663 
664     // Make sure that the timestamp is being overwritten.
665     checkMetadata(&buffer, /*numElements=*/0, /*startTime=*/expectedTimestamp,
666                   /*endTime=*/expectedTimestamp, atomId);
667 
668     EXPECT_EQ(AStatsEvent_getErrors(event), 0);
669     AStatsEvent_release(event);
670 }
671 
TEST(StatsEventTest,TestAttributionChainTooLongError)672 TEST(StatsEventTest, TestAttributionChainTooLongError) {
673     uint32_t atomId = 100;
674     uint8_t numNodes = 128;
675     uint32_t uids[numNodes];
676     vector<string> tags(numNodes);  // storage that cTag elements point to
677     const char* cTags[numNodes];
678     for (int i = 0; i < (int)numNodes; i++) {
679         uids[i] = i;
680         if (0 == i) {
681             tags.push_back("");
682             cTags[i] = nullptr;
683         } else {
684             tags.push_back("test" + std::to_string(i));
685             cTags[i] = tags[i].c_str();
686         }
687     }
688 
689     AStatsEvent* event = AStatsEvent_obtain();
690     AStatsEvent_setAtomId(event, atomId);
691     AStatsEvent_writeAttributionChain(event, uids, cTags, numNodes);
692     AStatsEvent_build(event);
693 
694     uint32_t errors = AStatsEvent_getErrors(event);
695     EXPECT_EQ(errors & ERROR_ATTRIBUTION_CHAIN_TOO_LONG, ERROR_ATTRIBUTION_CHAIN_TOO_LONG);
696 }
697 
TEST(StatsEventTest,TestListTooLongError)698 TEST(StatsEventTest, TestListTooLongError) {
699     uint32_t atomId = 100;
700     uint8_t numElements = 128;
701     int32_t int32Array[128] = {1};
702 
703     AStatsEvent* event = AStatsEvent_obtain();
704     AStatsEvent_setAtomId(event, atomId);
705     AStatsEvent_writeInt32Array(event, int32Array, numElements);
706     AStatsEvent_build(event);
707 
708     uint32_t errors = AStatsEvent_getErrors(event);
709     EXPECT_EQ(errors & ERROR_LIST_TOO_LONG, ERROR_LIST_TOO_LONG);
710 }
711