1 /*
2 * Copyright (C) 2017, 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 <gtest/gtest.h>
18 #include <stdio.h>
19
20 #include "Collation.h"
21 #include "frameworks/proto_logging/stats/stats_log_api_gen/test.pb.h"
22
23 namespace android {
24 namespace stats_log_api_gen {
25
26 using std::map;
27 using std::vector;
28
29 /**
30 * Return whether the map contains a vector of the elements provided.
31 */
map_contains_vector(const SignatureInfoMap & s,int count,...)32 static bool map_contains_vector(const SignatureInfoMap& s, int count, ...) {
33 va_list args;
34 vector<java_type_t> v(count);
35
36 va_start(args, count);
37 for (int i = 0; i < count; i++) {
38 v[i] = static_cast<java_type_t>(va_arg(args, int));
39 }
40 va_end(args);
41
42 return s.find(v) != s.end();
43 }
44
45 /**
46 * Expect that the provided map contains the elements provided.
47 */
48 #define EXPECT_MAP_CONTAINS_SIGNATURE(s, ...) \
49 do { \
50 int count = sizeof((int[]){__VA_ARGS__}) / sizeof(int); \
51 EXPECT_TRUE(map_contains_vector(s, count, __VA_ARGS__)); \
52 } while (0)
53
54 /** Expects that the provided atom has no enum values for any field. */
55 #define EXPECT_NO_ENUM_FIELD(atom) \
56 do { \
57 for (vector<AtomField>::const_iterator field = atom->fields.begin(); \
58 field != atom->fields.end(); field++) { \
59 EXPECT_TRUE(field->enumValues.empty()); \
60 } \
61 } while (0)
62
63 /** Expects that exactly one specific field has expected enum values. */
64 #define EXPECT_HAS_ENUM_FIELD(atom, field_name, values) \
65 do { \
66 for (vector<AtomField>::const_iterator field = atom->fields.begin(); \
67 field != atom->fields.end(); field++) { \
68 if (field->name == field_name) { \
69 EXPECT_EQ(field->enumValues, values); \
70 } else { \
71 EXPECT_TRUE(field->enumValues.empty()); \
72 } \
73 } \
74 } while (0)
75
76 /**
77 * Test a correct collation, with all the types.
78 */
TEST(CollationTest,CollateStats)79 TEST(CollationTest, CollateStats) {
80 Atoms atoms;
81 int errorCount = collate_atoms(Event::descriptor(), DEFAULT_MODULE_NAME, &atoms);
82
83 EXPECT_EQ(0, errorCount);
84 EXPECT_EQ(3ul, atoms.signatureInfoMap.size());
85
86 // IntAtom, AnotherIntAtom
87 EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT);
88
89 // OutOfOrderAtom
90 EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT, JAVA_TYPE_INT);
91
92 // AllTypesAtom
93 EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap,
94 JAVA_TYPE_ATTRIBUTION_CHAIN, // AttributionChain
95 JAVA_TYPE_FLOAT, // float
96 JAVA_TYPE_LONG, // int64
97 JAVA_TYPE_LONG, // uint64
98 JAVA_TYPE_INT, // int32
99 JAVA_TYPE_LONG, // fixed64
100 JAVA_TYPE_INT, // fixed32
101 JAVA_TYPE_BOOLEAN, // bool
102 JAVA_TYPE_STRING, // string
103 JAVA_TYPE_INT, // uint32
104 JAVA_TYPE_INT, // AnEnum
105 JAVA_TYPE_INT, // sfixed32
106 JAVA_TYPE_LONG, // sfixed64
107 JAVA_TYPE_INT, // sint32
108 JAVA_TYPE_LONG // sint64
109 );
110
111 EXPECT_EQ(4ul, atoms.decls.size());
112
113 AtomDeclSet::const_iterator atomIt = atoms.decls.begin();
114 EXPECT_EQ(1, (*atomIt)->code);
115 EXPECT_EQ("int_atom", (*atomIt)->name);
116 EXPECT_EQ("IntAtom", (*atomIt)->message);
117 EXPECT_NO_ENUM_FIELD((*atomIt));
118 atomIt++;
119
120 EXPECT_EQ(2, (*atomIt)->code);
121 EXPECT_EQ("out_of_order_atom", (*atomIt)->name);
122 EXPECT_EQ("OutOfOrderAtom", (*atomIt)->message);
123 EXPECT_NO_ENUM_FIELD((*atomIt));
124 atomIt++;
125
126 EXPECT_EQ(3, (*atomIt)->code);
127 EXPECT_EQ("another_int_atom", (*atomIt)->name);
128 EXPECT_EQ("AnotherIntAtom", (*atomIt)->message);
129 EXPECT_NO_ENUM_FIELD((*atomIt));
130 atomIt++;
131
132 EXPECT_EQ(4, (*atomIt)->code);
133 EXPECT_EQ("all_types_atom", (*atomIt)->name);
134 EXPECT_EQ("AllTypesAtom", (*atomIt)->message);
135 map<int, string> enumValues;
136 enumValues[0] = "VALUE0";
137 enumValues[1] = "VALUE1";
138 EXPECT_HAS_ENUM_FIELD((*atomIt), "enum_field", enumValues);
139 atomIt++;
140
141 EXPECT_EQ(atoms.decls.end(), atomIt);
142 }
143
144 /**
145 * Test that event class that contains stuff other than the atoms is rejected.
146 */
TEST(CollationTest,NonMessageTypeFails)147 TEST(CollationTest, NonMessageTypeFails) {
148 Atoms atoms;
149 int errorCount = collate_atoms(IntAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
150
151 EXPECT_EQ(1, errorCount);
152 }
153
154 /**
155 * Test that atoms that have non-primitive types or repeated fields are
156 * rejected.
157 */
TEST(CollationTest,FailOnBadTypes)158 TEST(CollationTest, FailOnBadTypes) {
159 Atoms atoms;
160 int errorCount = collate_atoms(BadTypesEvent::descriptor(), DEFAULT_MODULE_NAME, &atoms);
161
162 EXPECT_EQ(4, errorCount);
163 }
164
165 /**
166 * Test that atoms that skip field numbers (in the first position) are rejected.
167 */
TEST(CollationTest,FailOnSkippedFieldsSingle)168 TEST(CollationTest, FailOnSkippedFieldsSingle) {
169 Atoms atoms;
170 int errorCount =
171 collate_atoms(BadSkippedFieldSingle::descriptor(), DEFAULT_MODULE_NAME, &atoms);
172
173 EXPECT_EQ(1, errorCount);
174 }
175
176 /**
177 * Test that atoms that skip field numbers (not in the first position, and
178 * multiple times) are rejected.
179 */
TEST(CollationTest,FailOnSkippedFieldsMultiple)180 TEST(CollationTest, FailOnSkippedFieldsMultiple) {
181 Atoms atoms;
182 int errorCount =
183 collate_atoms(BadSkippedFieldMultiple::descriptor(), DEFAULT_MODULE_NAME, &atoms);
184
185 EXPECT_EQ(2, errorCount);
186 }
187
188 /**
189 * Test that atoms that have an attribution chain not in the first position are
190 * rejected.
191 */
TEST(CollationTest,FailBadAttributionNodePosition)192 TEST(CollationTest, FailBadAttributionNodePosition) {
193 Atoms atoms;
194 int errorCount =
195 collate_atoms(BadAttributionNodePosition::descriptor(), DEFAULT_MODULE_NAME, &atoms);
196
197 EXPECT_EQ(1, errorCount);
198 }
199
TEST(CollationTest,FailOnBadStateAtomOptions)200 TEST(CollationTest, FailOnBadStateAtomOptions) {
201 Atoms atoms;
202 int errorCount = collate_atoms(BadStateAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
203
204 EXPECT_EQ(3, errorCount);
205 }
206
TEST(CollationTest,PassOnGoodStateAtomOptions)207 TEST(CollationTest, PassOnGoodStateAtomOptions) {
208 Atoms atoms;
209 int errorCount = collate_atoms(GoodStateAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
210 EXPECT_EQ(0, errorCount);
211 }
212
TEST(CollationTest,PassOnGoodBinaryFieldAtom)213 TEST(CollationTest, PassOnGoodBinaryFieldAtom) {
214 Atoms atoms;
215 int errorCount =
216 collate_atoms(GoodEventWithBinaryFieldAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
217 EXPECT_EQ(0, errorCount);
218 }
219
TEST(CollationTest,FailOnBadBinaryFieldAtom)220 TEST(CollationTest, FailOnBadBinaryFieldAtom) {
221 Atoms atoms;
222 int errorCount =
223 collate_atoms(BadEventWithBinaryFieldAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
224 EXPECT_GT(errorCount, 0);
225 }
226
TEST(CollationTest,PassOnLogFromModuleAtom)227 TEST(CollationTest, PassOnLogFromModuleAtom) {
228 Atoms atoms;
229 int errorCount = collate_atoms(ModuleAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
230 EXPECT_EQ(errorCount, 0);
231 EXPECT_EQ(atoms.decls.size(), 4ul);
232 }
233
TEST(CollationTest,RecognizeModuleAtom)234 TEST(CollationTest, RecognizeModuleAtom) {
235 Atoms atoms;
236 int errorCount = collate_atoms(ModuleAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
237 EXPECT_EQ(errorCount, 0);
238 EXPECT_EQ(atoms.decls.size(), 4ul);
239 EXPECT_EQ(atoms.signatureInfoMap.size(), 2u);
240 EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT);
241 EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_STRING);
242
243 SignatureInfoMap::const_iterator signatureInfoMapIt;
244 const vector<java_type_t>* signature;
245 const FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet;
246 FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt;
247 const AtomDeclSet* atomDeclSet;
248 AtomDeclSet::const_iterator atomDeclSetIt;
249 AtomDecl* atomDecl;
250 FieldNumberToAnnotations* fieldNumberToAnnotations;
251 FieldNumberToAnnotations::const_iterator fieldNumberToAnnotationsIt;
252 const AnnotationSet* annotationSet;
253 AnnotationSet::const_iterator annotationSetIt;
254 Annotation* annotation;
255
256 signatureInfoMapIt = atoms.signatureInfoMap.begin();
257 signature = &(signatureInfoMapIt->first);
258 fieldNumberToAtomDeclSet = &signatureInfoMapIt->second;
259 EXPECT_EQ(1ul, signature->size());
260 EXPECT_EQ(JAVA_TYPE_INT, signature->at(0));
261 EXPECT_EQ(1ul, fieldNumberToAtomDeclSet->size());
262 fieldNumberToAtomDeclSetIt = fieldNumberToAtomDeclSet->begin();
263 EXPECT_EQ(1, fieldNumberToAtomDeclSetIt->first);
264 atomDeclSet = &fieldNumberToAtomDeclSetIt->second;
265 EXPECT_EQ(2ul, atomDeclSet->size());
266 atomDeclSetIt = atomDeclSet->begin();
267 atomDecl = atomDeclSetIt->get();
268 EXPECT_EQ(1, atomDecl->code);
269 fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
270 fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
271 EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
272 annotationSet = &fieldNumberToAnnotationsIt->second;
273 EXPECT_EQ(1ul, annotationSet->size());
274 annotationSetIt = annotationSet->begin();
275 annotation = annotationSetIt->get();
276 EXPECT_EQ(ANNOTATION_ID_IS_UID, annotation->annotationId);
277 EXPECT_EQ(1, annotation->atomId);
278 EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
279 EXPECT_TRUE(annotation->value.boolValue);
280
281 atomDeclSetIt++;
282 atomDecl = atomDeclSetIt->get();
283 EXPECT_EQ(3, atomDecl->code);
284 fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
285 fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
286 EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
287 annotationSet = &fieldNumberToAnnotationsIt->second;
288 EXPECT_EQ(1ul, annotationSet->size());
289 annotationSetIt = annotationSet->begin();
290 annotation = annotationSetIt->get();
291 EXPECT_EQ(ANNOTATION_ID_EXCLUSIVE_STATE, annotation->annotationId);
292 EXPECT_EQ(3, annotation->atomId);
293 EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
294 EXPECT_TRUE(annotation->value.boolValue);
295
296 signatureInfoMapIt++;
297 signature = &signatureInfoMapIt->first;
298 fieldNumberToAtomDeclSet = &signatureInfoMapIt->second;
299 EXPECT_EQ(1ul, signature->size());
300 EXPECT_EQ(JAVA_TYPE_STRING, signature->at(0));
301 EXPECT_EQ(0ul, fieldNumberToAtomDeclSet->size());
302 }
303
TEST(CollationTest,RecognizeModule1Atom)304 TEST(CollationTest, RecognizeModule1Atom) {
305 Atoms atoms;
306 const string moduleName = "module1";
307 int errorCount = collate_atoms(ModuleAtoms::descriptor(), moduleName, &atoms);
308 EXPECT_EQ(errorCount, 0);
309 EXPECT_EQ(atoms.decls.size(), 2ul);
310 EXPECT_EQ(atoms.signatureInfoMap.size(), 1u);
311 EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT);
312
313 SignatureInfoMap::const_iterator signatureInfoMapIt;
314 const vector<java_type_t>* signature;
315 const FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet;
316 FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt;
317 const AtomDeclSet* atomDeclSet;
318 AtomDeclSet::const_iterator atomDeclSetIt;
319 AtomDecl* atomDecl;
320 FieldNumberToAnnotations* fieldNumberToAnnotations;
321 FieldNumberToAnnotations::const_iterator fieldNumberToAnnotationsIt;
322 const AnnotationSet* annotationSet;
323 AnnotationSet::const_iterator annotationSetIt;
324 Annotation* annotation;
325
326 signatureInfoMapIt = atoms.signatureInfoMap.begin();
327 signature = &(signatureInfoMapIt->first);
328 fieldNumberToAtomDeclSet = &signatureInfoMapIt->second;
329 EXPECT_EQ(1ul, signature->size());
330 EXPECT_EQ(JAVA_TYPE_INT, signature->at(0));
331 EXPECT_EQ(1ul, fieldNumberToAtomDeclSet->size());
332 fieldNumberToAtomDeclSetIt = fieldNumberToAtomDeclSet->begin();
333 EXPECT_EQ(1, fieldNumberToAtomDeclSetIt->first);
334 atomDeclSet = &fieldNumberToAtomDeclSetIt->second;
335 EXPECT_EQ(2ul, atomDeclSet->size());
336 atomDeclSetIt = atomDeclSet->begin();
337 atomDecl = atomDeclSetIt->get();
338 EXPECT_EQ(1, atomDecl->code);
339 fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
340 fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
341 EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
342 annotationSet = &fieldNumberToAnnotationsIt->second;
343 EXPECT_EQ(1ul, annotationSet->size());
344 annotationSetIt = annotationSet->begin();
345 annotation = annotationSetIt->get();
346 EXPECT_EQ(ANNOTATION_ID_IS_UID, annotation->annotationId);
347 EXPECT_EQ(1, annotation->atomId);
348 EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
349 EXPECT_TRUE(annotation->value.boolValue);
350
351 atomDeclSetIt++;
352 atomDecl = atomDeclSetIt->get();
353 EXPECT_EQ(3, atomDecl->code);
354 fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
355 fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
356 EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
357 annotationSet = &fieldNumberToAnnotationsIt->second;
358 EXPECT_EQ(1ul, annotationSet->size());
359 annotationSetIt = annotationSet->begin();
360 annotation = annotationSetIt->get();
361 EXPECT_EQ(ANNOTATION_ID_EXCLUSIVE_STATE, annotation->annotationId);
362 EXPECT_EQ(3, annotation->atomId);
363 EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
364 EXPECT_TRUE(annotation->value.boolValue);
365 }
366
367 /**
368 * Test that an atom is not a pushed nor pulled atom.
369 */
TEST(CollationTest,InvalidAtomType)370 TEST(CollationTest, InvalidAtomType) {
371 Atoms atoms;
372 int errorCount = collate_atoms(NotAPushNorPullAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
373
374 EXPECT_EQ(1, errorCount);
375 }
376
377 /**
378 * Test that an atom was not declared in a `oneof` field.
379 */
TEST(CollationTest,AtomNotDeclaredInAOneof)380 TEST(CollationTest, AtomNotDeclaredInAOneof) {
381 Atoms atoms;
382 int errorCount = collate_atoms(AtomNotInAOneof::descriptor(), DEFAULT_MODULE_NAME, &atoms);
383
384 EXPECT_EQ(1, errorCount);
385 }
386
387 /**
388 * Test a correct collation with pushed and pulled atoms.
389 */
TEST(CollationTest,CollatePushedAndPulledAtoms)390 TEST(CollationTest, CollatePushedAndPulledAtoms) {
391 Atoms atoms;
392 int errorCount = collate_atoms(PushedAndPulledAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
393
394 EXPECT_EQ(0, errorCount);
395 EXPECT_EQ(1ul, atoms.signatureInfoMap.size());
396 EXPECT_EQ(2ul, atoms.pulledAtomsSignatureInfoMap.size());
397
398 // IntAtom
399 EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT);
400
401 // AnotherIntAtom
402 EXPECT_MAP_CONTAINS_SIGNATURE(atoms.pulledAtomsSignatureInfoMap, JAVA_TYPE_INT);
403
404 // OutOfOrderAtom
405 EXPECT_MAP_CONTAINS_SIGNATURE(atoms.pulledAtomsSignatureInfoMap, JAVA_TYPE_INT, JAVA_TYPE_INT);
406
407 EXPECT_EQ(3ul, atoms.decls.size());
408
409 AtomDeclSet::const_iterator atomIt = atoms.decls.begin();
410 EXPECT_EQ(1, (*atomIt)->code);
411 EXPECT_EQ("int_atom_1", (*atomIt)->name);
412 EXPECT_EQ("IntAtom", (*atomIt)->message);
413 EXPECT_NO_ENUM_FIELD((*atomIt));
414 atomIt++;
415
416 EXPECT_EQ(10, (*atomIt)->code);
417 EXPECT_EQ("another_int_atom", (*atomIt)->name);
418 EXPECT_EQ("AnotherIntAtom", (*atomIt)->message);
419 EXPECT_NO_ENUM_FIELD((*atomIt));
420 atomIt++;
421
422 EXPECT_EQ(11, (*atomIt)->code);
423 EXPECT_EQ("out_of_order_atom", (*atomIt)->name);
424 EXPECT_EQ("OutOfOrderAtom", (*atomIt)->message);
425 EXPECT_NO_ENUM_FIELD((*atomIt));
426 atomIt++;
427
428 EXPECT_EQ(atoms.decls.end(), atomIt);
429 }
430
431 } // namespace stats_log_api_gen
432 } // namespace android
433