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