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
19 #include "frameworks/base/tools/stats_log_api_gen/test.pb.h"
20 #include "Collation.h"
21
22 #include <stdio.h>
23
24 namespace android {
25 namespace stats_log_api_gen {
26
27 using std::map;
28 using std::set;
29 using std::vector;
30
31 /**
32 * Return whether the set contains a vector of the elements provided.
33 */
34 static bool
set_contains_vector(const map<vector<java_type_t>,set<string>> & s,int count,...)35 set_contains_vector(const map<vector<java_type_t>, set<string>>& s, int count, ...)
36 {
37 va_list args;
38 vector<java_type_t> v;
39
40 va_start(args, count);
41 for (int i=0; i<count; i++) {
42 v.push_back((java_type_t)va_arg(args, int));
43 }
44 va_end(args);
45
46 return s.find(v) != s.end();
47 }
48
49 /**
50 * Expect that the provided set contains the elements provided.
51 */
52 #define EXPECT_SET_CONTAINS_SIGNATURE(s, ...) \
53 do { \
54 int count = sizeof((int[]){__VA_ARGS__})/sizeof(int); \
55 EXPECT_TRUE(set_contains_vector(s, count, __VA_ARGS__)); \
56 } while(0)
57
58 /** Expects that the provided atom has no enum values for any field. */
59 #define EXPECT_NO_ENUM_FIELD(atom) \
60 do { \
61 for (vector<AtomField>::const_iterator field = atom->fields.begin(); \
62 field != atom->fields.end(); field++) { \
63 EXPECT_TRUE(field->enumValues.empty()); \
64 } \
65 } while(0)
66
67 /** Expects that exactly one specific field has expected enum values. */
68 #define EXPECT_HAS_ENUM_FIELD(atom, field_name, values) \
69 do { \
70 for (vector<AtomField>::const_iterator field = atom->fields.begin(); \
71 field != atom->fields.end(); field++) { \
72 if (field->name == field_name) { \
73 EXPECT_EQ(field->enumValues, values); \
74 } else { \
75 EXPECT_TRUE(field->enumValues.empty()); \
76 } \
77 } \
78 } while(0)
79
80
81 /**
82 * Test a correct collation, with all the types.
83 */
TEST(CollationTest,CollateStats)84 TEST(CollationTest, CollateStats) {
85 Atoms atoms;
86 int errorCount = collate_atoms(Event::descriptor(), &atoms);
87
88 EXPECT_EQ(0, errorCount);
89 EXPECT_EQ(3ul, atoms.signatures_to_modules.size());
90
91 // IntAtom, AnotherIntAtom
92 EXPECT_SET_CONTAINS_SIGNATURE(atoms.signatures_to_modules, JAVA_TYPE_INT);
93
94 // OutOfOrderAtom
95 EXPECT_SET_CONTAINS_SIGNATURE(atoms.signatures_to_modules, JAVA_TYPE_INT, JAVA_TYPE_INT);
96
97 // AllTypesAtom
98 EXPECT_SET_CONTAINS_SIGNATURE(
99 atoms.signatures_to_modules,
100 JAVA_TYPE_ATTRIBUTION_CHAIN, // AttributionChain
101 JAVA_TYPE_DOUBLE, // double
102 JAVA_TYPE_FLOAT, // float
103 JAVA_TYPE_LONG, // int64
104 JAVA_TYPE_LONG, // uint64
105 JAVA_TYPE_INT, // int32
106 JAVA_TYPE_LONG, // fixed64
107 JAVA_TYPE_INT, // fixed32
108 JAVA_TYPE_BOOLEAN, // bool
109 JAVA_TYPE_STRING, // string
110 JAVA_TYPE_INT, // uint32
111 JAVA_TYPE_INT, // AnEnum
112 JAVA_TYPE_INT, // sfixed32
113 JAVA_TYPE_LONG, // sfixed64
114 JAVA_TYPE_INT, // sint32
115 JAVA_TYPE_LONG // sint64
116 );
117
118 set<AtomDecl>::const_iterator atom = atoms.decls.begin();
119 EXPECT_EQ(1, atom->code);
120 EXPECT_EQ("int_atom", atom->name);
121 EXPECT_EQ("IntAtom", atom->message);
122 EXPECT_NO_ENUM_FIELD(atom);
123 atom++;
124
125 EXPECT_EQ(2, atom->code);
126 EXPECT_EQ("out_of_order_atom", atom->name);
127 EXPECT_EQ("OutOfOrderAtom", atom->message);
128 EXPECT_NO_ENUM_FIELD(atom);
129 atom++;
130
131 EXPECT_EQ(3, atom->code);
132 EXPECT_EQ("another_int_atom", atom->name);
133 EXPECT_EQ("AnotherIntAtom", atom->message);
134 EXPECT_NO_ENUM_FIELD(atom);
135 atom++;
136
137 EXPECT_EQ(4, atom->code);
138 EXPECT_EQ("all_types_atom", atom->name);
139 EXPECT_EQ("AllTypesAtom", atom->message);
140 map<int, string> enumValues;
141 enumValues[0] = "VALUE0";
142 enumValues[1] = "VALUE1";
143 EXPECT_HAS_ENUM_FIELD(atom, "enum_field", enumValues);
144 atom++;
145
146 EXPECT_TRUE(atom == atoms.decls.end());
147 }
148
149 /**
150 * Test that event class that contains stuff other than the atoms is rejected.
151 */
TEST(CollationTest,NonMessageTypeFails)152 TEST(CollationTest, NonMessageTypeFails) {
153 Atoms atoms;
154 int errorCount = collate_atoms(IntAtom::descriptor(), &atoms);
155
156 EXPECT_EQ(1, errorCount);
157 }
158
159 /**
160 * Test that atoms that have non-primitive types are rejected.
161 */
TEST(CollationTest,FailOnBadTypes)162 TEST(CollationTest, FailOnBadTypes) {
163 Atoms atoms;
164 int errorCount = collate_atoms(BadTypesEvent::descriptor(), &atoms);
165
166 EXPECT_EQ(2, errorCount);
167 }
168
169 /**
170 * Test that atoms that skip field numbers (in the first position) are rejected.
171 */
TEST(CollationTest,FailOnSkippedFieldsSingle)172 TEST(CollationTest, FailOnSkippedFieldsSingle) {
173 Atoms atoms;
174 int errorCount = collate_atoms(BadSkippedFieldSingle::descriptor(), &atoms);
175
176 EXPECT_EQ(1, errorCount);
177 }
178
179 /**
180 * Test that atoms that skip field numbers (not in the first position, and multiple
181 * times) are rejected.
182 */
TEST(CollationTest,FailOnSkippedFieldsMultiple)183 TEST(CollationTest, FailOnSkippedFieldsMultiple) {
184 Atoms atoms;
185 int errorCount = collate_atoms(BadSkippedFieldMultiple::descriptor(), &atoms);
186
187 EXPECT_EQ(2, errorCount);
188 }
189
190 /**
191 * Test that atoms that have an attribution chain not in the first position are
192 * rejected.
193 */
TEST(CollationTest,FailBadAttributionNodePosition)194 TEST(CollationTest, FailBadAttributionNodePosition) {
195 Atoms atoms;
196 int errorCount =
197 collate_atoms(BadAttributionNodePosition::descriptor(), &atoms);
198
199 EXPECT_EQ(1, errorCount);
200 }
201
TEST(CollationTest,FailOnBadStateAtomOptions)202 TEST(CollationTest, FailOnBadStateAtomOptions) {
203 Atoms atoms;
204 int errorCount = collate_atoms(BadStateAtoms::descriptor(), &atoms);
205
206 EXPECT_EQ(3, errorCount);
207 }
208
TEST(CollationTest,PassOnGoodStateAtomOptions)209 TEST(CollationTest, PassOnGoodStateAtomOptions) {
210 Atoms atoms;
211 int errorCount = collate_atoms(GoodStateAtoms::descriptor(), &atoms);
212 EXPECT_EQ(0, errorCount);
213 }
214
TEST(CollationTest,PassOnGoodBinaryFieldAtom)215 TEST(CollationTest, PassOnGoodBinaryFieldAtom) {
216 Atoms atoms;
217 int errorCount =
218 collate_atoms(GoodEventWithBinaryFieldAtom::descriptor(), &atoms);
219 EXPECT_EQ(0, errorCount);
220 }
221
TEST(CollationTest,FailOnBadBinaryFieldAtom)222 TEST(CollationTest, FailOnBadBinaryFieldAtom) {
223 Atoms atoms;
224 int errorCount =
225 collate_atoms(BadEventWithBinaryFieldAtom::descriptor(), &atoms);
226 EXPECT_TRUE(errorCount > 0);
227 }
228
TEST(CollationTest,PassOnWhitelistedAtom)229 TEST(CollationTest, PassOnWhitelistedAtom) {
230 Atoms atoms;
231 int errorCount = collate_atoms(ListedAtoms::descriptor(), &atoms);
232 EXPECT_EQ(errorCount, 0);
233 EXPECT_EQ(atoms.decls.size(), 2ul);
234 }
235
TEST(CollationTest,RecogniseWhitelistedAtom)236 TEST(CollationTest, RecogniseWhitelistedAtom) {
237 Atoms atoms;
238 collate_atoms(ListedAtoms::descriptor(), &atoms);
239 for (const auto& atomDecl : atoms.decls) {
240 if (atomDecl.code == 1) {
241 EXPECT_TRUE(atomDecl.whitelisted);
242 } else {
243 EXPECT_FALSE(atomDecl.whitelisted);
244 }
245 }
246 }
247
TEST(CollationTest,PassOnLogFromModuleAtom)248 TEST(CollationTest, PassOnLogFromModuleAtom) {
249 Atoms atoms;
250 int errorCount = collate_atoms(ModuleAtoms::descriptor(), &atoms);
251 EXPECT_EQ(errorCount, 0);
252 EXPECT_EQ(atoms.decls.size(), 3ul);
253 }
254
TEST(CollationTest,RecognizeModuleAtom)255 TEST(CollationTest, RecognizeModuleAtom) {
256 Atoms atoms;
257 int errorCount = collate_atoms(ModuleAtoms::descriptor(), &atoms);
258 EXPECT_EQ(errorCount, 0);
259 EXPECT_EQ(atoms.decls.size(), 3ul);
260 for (const auto& atomDecl: atoms.decls) {
261 if (atomDecl.code == 1) {
262 EXPECT_TRUE(atomDecl.hasModule);
263 EXPECT_EQ(atomDecl.moduleName, "module1");
264 } else if (atomDecl.code == 2) {
265 EXPECT_TRUE(atomDecl.hasModule);
266 EXPECT_EQ(atomDecl.moduleName, "module2");
267 } else {
268 EXPECT_FALSE(atomDecl.hasModule);
269 }
270 }
271
272 EXPECT_EQ(atoms.signatures_to_modules.size(), 2u);
273 EXPECT_SET_CONTAINS_SIGNATURE(atoms.signatures_to_modules, JAVA_TYPE_INT);
274 EXPECT_SET_CONTAINS_SIGNATURE(atoms.signatures_to_modules, JAVA_TYPE_STRING);
275 for (auto signature_to_modules_it : atoms.signatures_to_modules) {
276 vector<java_type_t> signature = signature_to_modules_it.first;
277 if (signature[0] == JAVA_TYPE_STRING) {
278 EXPECT_EQ(signature_to_modules_it.second.size(), 0u);
279 } else if (signature[0] == JAVA_TYPE_INT) {
280 set<string> modules = signature_to_modules_it.second;
281 EXPECT_EQ(modules.size(), 2u);
282 // Assert that the set contains "module1" and "module2".
283 EXPECT_NE(modules.find("module1"), modules.end());
284 EXPECT_NE(modules.find("module2"), modules.end());
285 }
286 }
287 }
288
289 } // namespace stats_log_api_gen
290 } // namespace android