blob: 27b72eb1edbe53fd8e2f80a0d841562a4497e529 [file] [log] [blame]
Andy Hungc89c8dc2019-10-16 17:48:21 -07001/*
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#define LOG_TAG "mediametrics_tests"
18#include <utils/Log.h>
19
Ray Essick40e8e5e2019-12-05 20:19:40 -080020#include "MediaMetricsService.h"
Andy Hungc89c8dc2019-10-16 17:48:21 -070021
22#include <stdio.h>
23
24#include <gtest/gtest.h>
Ray Essickf27e9872019-12-07 06:28:46 -080025#include <media/MediaMetricsItem.h>
Andy Hungc89c8dc2019-10-16 17:48:21 -070026
27using namespace android;
28
Andy Hung06f3aba2019-12-03 16:36:42 -080029static size_t countNewlines(const char *s) {
30 size_t count = 0;
31 while ((s = strchr(s, '\n')) != nullptr) {
32 ++s;
33 ++count;
34 }
35 return count;
36}
37
Andy Hung37de9b72020-01-02 13:54:05 -080038TEST(mediametrics_tests, startsWith) {
39 std::string s("test");
40 ASSERT_EQ(true, android::mediametrics::startsWith(s, "te"));
41 ASSERT_EQ(true, android::mediametrics::startsWith(s, std::string("tes")));
42 ASSERT_EQ(false, android::mediametrics::startsWith(s, "ts"));
43 ASSERT_EQ(false, android::mediametrics::startsWith(s, std::string("est")));
44}
45
46TEST(mediametrics_tests, defer) {
47 bool check = false;
48 {
49 android::mediametrics::Defer defer([&] { check = true; });
50 ASSERT_EQ(false, check);
51 }
52 ASSERT_EQ(true, check);
53}
54
Andy Hung0f7ad8c2020-01-03 13:24:34 -080055TEST(mediametrics_tests, shared_ptr_wrap) {
56 // Test shared pointer wrap with simple access
57 android::mediametrics::SharedPtrWrap<std::string> s("123");
58 ASSERT_EQ('1', s->at(0));
59 ASSERT_EQ('2', s->at(1));
60 s->push_back('4');
61 ASSERT_EQ('4', s->at(3));
62
63 const android::mediametrics::SharedPtrWrap<std::string> s2("345");
64 ASSERT_EQ('3', s2->operator[](0)); // s2[0] == '3'
65 // we allow modification through a const shared pointer wrap
66 // for compatibility with shared_ptr.
67 s2->push_back('6');
68 ASSERT_EQ('6', s2->operator[](3)); // s2[3] == '6'
69
70 android::mediametrics::SharedPtrWrap<std::string> s3("");
71 s3.set(std::make_shared<std::string>("abc"));
72 ASSERT_EQ('b', s3->operator[](1)); // s2[1] = 'b';
73
74 // Use Thunk to check whether the destructor was called prematurely
75 // when setting the shared ptr wrap in the middle of a method.
76
77 class Thunk {
78 std::function<void(int)> mF;
79 const int mFinal;
80
81 public:
82 Thunk(decltype(mF) f, int final) : mF(f), mFinal(final) {}
83 ~Thunk() { mF(mFinal); }
84 void thunk(int value) { mF(value); }
85 };
86
87 int counter = 0;
88 android::mediametrics::SharedPtrWrap<Thunk> s4(
89 [&](int value) {
90 s4.set(std::make_shared<Thunk>([](int){}, 0)); // recursively set s4 while in s4.
91 ++counter;
92 ASSERT_EQ(value, counter); // on thunk() value is 1, on destructor this is 2.
93 }, 2);
94
95 // This will fail if the shared ptr wrap doesn't hold a ref count during method access.
96 s4->thunk(1);
97}
98
99TEST(mediametrics_tests, lock_wrap) {
100 // Test lock wrap with simple access
101 android::mediametrics::LockWrap<std::string> s("123");
102 ASSERT_EQ('1', s->at(0));
103 ASSERT_EQ('2', s->at(1));
104 s->push_back('4');
105 ASSERT_EQ('4', s->at(3));
106
107 const android::mediametrics::LockWrap<std::string> s2("345");
108 ASSERT_EQ('3', s2->operator[](0)); // s2[0] == '3'
109 // note: we can't modify s2 due to const, s2->push_back('6');
110
111 android::mediametrics::LockWrap<std::string> s3("");
112 s3->operator=("abc");
113 ASSERT_EQ('b', s3->operator[](1)); // s2[1] = 'b';
114
Andy Hung42b99302020-01-10 12:01:18 -0800115 // Check that we can recursively hold lock.
116 android::mediametrics::LockWrap<std::vector<int>> v{std::initializer_list<int>{1, 2}};
117 v->push_back(3);
118 v->push_back(4);
119 ASSERT_EQ(1, v->operator[](0));
120 ASSERT_EQ(2, v->operator[](1));
121 ASSERT_EQ(3, v->operator[](2));
122 ASSERT_EQ(4, v->operator[](3));
123 // The end of the full expression here requires recursive depth of 4.
124 ASSERT_EQ(10, v->operator[](0) + v->operator[](1) + v->operator[](2) + v->operator[](3));
125
126 // Mikhail's note: a non-recursive lock implementation could be used if one obtains
127 // the LockedPointer helper object like this and directly hold the lock through RAII,
128 // though it is trickier in use.
129 //
130 // We include an example here for completeness.
131 {
132 auto l = v.operator->();
133 ASSERT_EQ(10, l->operator[](0) + l->operator[](1) + l->operator[](2) + l->operator[](3));
134 }
135
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800136 // Use Thunk to check whether we have the lock when calling a method through LockWrap.
137
138 class Thunk {
139 std::function<void()> mF;
140
141 public:
142 Thunk(decltype(mF) f) : mF(f) {}
143 void thunk() { mF(); }
144 };
145
146 android::mediametrics::LockWrap<Thunk> s4([&]{
Andy Hung42b99302020-01-10 12:01:18 -0800147 ASSERT_EQ((size_t)1, s4.getRecursionDepth()); // we must be locked when thunk() is called.
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800148 });
149
Andy Hung42b99302020-01-10 12:01:18 -0800150 ASSERT_EQ((size_t)0, s4.getRecursionDepth());
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800151 // This will fail if we are not locked during method access.
152 s4->thunk();
Andy Hung42b99302020-01-10 12:01:18 -0800153 ASSERT_EQ((size_t)0, s4.getRecursionDepth());
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800154}
155
156TEST(mediametrics_tests, lock_wrap_multithread) {
157 class Accumulator {
158 int32_t value_ = 0;
159 public:
160 void add(int32_t incr) {
161 const int32_t temp = value_;
162 sleep(0); // yield
163 value_ = temp + incr;
164 }
165 int32_t get() { return value_; }
166 };
167
168 android::mediametrics::LockWrap<Accumulator> a{}; // locked accumulator succeeds
169 // auto a = std::make_shared<Accumulator>(); // this fails, only 50% adds atomic.
170
171 constexpr size_t THREADS = 100;
172 constexpr size_t ITERATIONS = 10;
173 constexpr int32_t INCREMENT = 1;
174
175 std::vector<std::future<void>> threads(THREADS);
176 for (size_t i = 0; i < THREADS; ++i) {
177 threads.push_back(std::async(std::launch::async, [&] {
178 for (size_t j = 0; j < ITERATIONS; ++j) {
179 a->add(INCREMENT);
180 }
181 }));
182 }
183 threads.clear();
184
185 // If the add operations are not atomic, value will be smaller than expected.
186 ASSERT_EQ(INCREMENT * THREADS * ITERATIONS, (size_t)a->get());
187}
188
Andy Hungc89c8dc2019-10-16 17:48:21 -0700189TEST(mediametrics_tests, instantiate) {
Ray Essickf27e9872019-12-07 06:28:46 -0800190 sp mediaMetrics = new MediaMetricsService();
Andy Hungc89c8dc2019-10-16 17:48:21 -0700191 status_t status;
192
Andy Hungc89c8dc2019-10-16 17:48:21 -0700193 // random keys ignored when empty
Ray Essickf27e9872019-12-07 06:28:46 -0800194 std::unique_ptr<mediametrics::Item> random_key(mediametrics::Item::create("random_key"));
Andy Hunga87e69c2019-10-18 10:07:40 -0700195 status = mediaMetrics->submit(random_key.get());
196 ASSERT_EQ(PERMISSION_DENIED, status);
Andy Hungc89c8dc2019-10-16 17:48:21 -0700197
198 // random keys ignored with data
Andy Hungc89c8dc2019-10-16 17:48:21 -0700199 random_key->setInt32("foo", 10);
Andy Hunga87e69c2019-10-18 10:07:40 -0700200 status = mediaMetrics->submit(random_key.get());
201 ASSERT_EQ(PERMISSION_DENIED, status);
Andy Hungc89c8dc2019-10-16 17:48:21 -0700202
203 // known keys ignored if empty
Ray Essickf27e9872019-12-07 06:28:46 -0800204 std::unique_ptr<mediametrics::Item> audiotrack_key(mediametrics::Item::create("audiotrack"));
Andy Hunga87e69c2019-10-18 10:07:40 -0700205 status = mediaMetrics->submit(audiotrack_key.get());
206 ASSERT_EQ(BAD_VALUE, status);
Andy Hungc89c8dc2019-10-16 17:48:21 -0700207
Andy Hunga87e69c2019-10-18 10:07:40 -0700208 // known keys not ignored if not empty
209 audiotrack_key->addInt32("foo", 10);
210 status = mediaMetrics->submit(audiotrack_key.get());
211 ASSERT_EQ(NO_ERROR, status);
Andy Hungc89c8dc2019-10-16 17:48:21 -0700212
Andy Hungaeef7882019-10-18 15:18:14 -0700213
214 /*
215 // fluent style that goes directly to mediametrics
Ray Essickf27e9872019-12-07 06:28:46 -0800216 ASSERT_EQ(true, mediametrics::Item("audiorecord")
Andy Hungaeef7882019-10-18 15:18:14 -0700217 .setInt32("value", 2)
218 .addInt32("bar", 1)
219 .addInt32("value", 3)
220 .selfrecord());
221 */
222
Andy Hungc89c8dc2019-10-16 17:48:21 -0700223 mediaMetrics->dump(fileno(stdout), {} /* args */);
224}
Andy Hungaeef7882019-10-18 15:18:14 -0700225
Andy Hunga85efab2019-12-23 11:41:29 -0800226TEST(mediametrics_tests, package_installer_check) {
227 ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
228 "abcd", "installer")); // ok, package name has no dot.
229 ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
230 "android.com", "installer")); // ok, package name starts with android
231
232 ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
233 "abc.def", "com.android.foo")); // ok, installer name starts with com.android
234 ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
235 "123.456", "com.google.bar")); // ok, installer name starts with com.google
236 ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
237 "r2.d2", "preload")); // ok, installer name is preload
238
239 ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
240 "abc.def", "installer")); // unknown installer
241 ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
242 "123.456", "installer")); // unknown installer
243 ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
244 "r2.d2", "preload23")); // unknown installer
245
246 ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
247 "com.android.foo", "abc.def")); // unknown installer
248 ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
249 "com.google.bar", "123.456")); // unknown installer
250}
251
Andy Hungaeef7882019-10-18 15:18:14 -0700252TEST(mediametrics_tests, item_manipulation) {
Ray Essickf27e9872019-12-07 06:28:46 -0800253 mediametrics::Item item("audiorecord");
Andy Hungaeef7882019-10-18 15:18:14 -0700254
255 item.setInt32("value", 2).addInt32("bar", 3).addInt32("value", 4);
256
257 int32_t i32;
258 ASSERT_TRUE(item.getInt32("value", &i32));
259 ASSERT_EQ(6, i32);
260
261 ASSERT_TRUE(item.getInt32("bar", &i32));
262 ASSERT_EQ(3, i32);
263
264 item.setInt64("big", INT64_MAX).setInt64("smaller", INT64_MAX - 1).addInt64("smaller", -2);
265
266 int64_t i64;
267 ASSERT_TRUE(item.getInt64("big", &i64));
268 ASSERT_EQ(INT64_MAX, i64);
269
270 ASSERT_TRUE(item.getInt64("smaller", &i64));
271 ASSERT_EQ(INT64_MAX - 3, i64);
272
273 item.setDouble("precise", 10.5).setDouble("small", 0.125).addDouble("precise", 0.25);
274
275 double d;
276 ASSERT_TRUE(item.getDouble("precise", &d));
277 ASSERT_EQ(10.75, d);
278
279 ASSERT_TRUE(item.getDouble("small", &d));
280 ASSERT_EQ(0.125, d);
281
282 char *s;
283 item.setCString("name", "Frank").setCString("mother", "June").setCString("mother", "July");
284 ASSERT_TRUE(item.getCString("name", &s));
285 ASSERT_EQ(0, strcmp(s, "Frank"));
286 free(s);
287
288 ASSERT_TRUE(item.getCString("mother", &s));
289 ASSERT_EQ(0, strcmp(s, "July")); // "July" overwrites "June"
290 free(s);
291
292 item.setRate("burgersPerHour", 5, 2);
293 int64_t b, h;
294 ASSERT_TRUE(item.getRate("burgersPerHour", &b, &h, &d));
295 ASSERT_EQ(5, b);
296 ASSERT_EQ(2, h);
297 ASSERT_EQ(2.5, d);
298
299 item.addRate("burgersPerHour", 4, 2);
300 ASSERT_TRUE(item.getRate("burgersPerHour", &b, &h, &d));
301 ASSERT_EQ(9, b);
302 ASSERT_EQ(4, h);
303 ASSERT_EQ(2.25, d);
304
305 printf("item: %s\n", item.toString().c_str());
306 fflush(stdout);
307
Ray Essickf27e9872019-12-07 06:28:46 -0800308 sp mediaMetrics = new MediaMetricsService();
Andy Hungaeef7882019-10-18 15:18:14 -0700309 status_t status = mediaMetrics->submit(&item);
310 ASSERT_EQ(NO_ERROR, status);
311 mediaMetrics->dump(fileno(stdout), {} /* args */);
312}
313
314TEST(mediametrics_tests, superbig_item) {
Ray Essickf27e9872019-12-07 06:28:46 -0800315 mediametrics::Item item("TheBigOne");
Andy Hungaeef7882019-10-18 15:18:14 -0700316 constexpr size_t count = 10000;
317
318 for (size_t i = 0; i < count; ++i) {
319 item.setInt32(std::to_string(i).c_str(), i);
320 }
321 for (size_t i = 0; i < count; ++i) {
322 int32_t i32;
323 ASSERT_TRUE(item.getInt32(std::to_string(i).c_str(), &i32));
324 ASSERT_EQ((int32_t)i, i32);
325 }
326}
327
328TEST(mediametrics_tests, superbig_item_removal) {
Ray Essickf27e9872019-12-07 06:28:46 -0800329 mediametrics::Item item("TheOddBigOne");
Andy Hungaeef7882019-10-18 15:18:14 -0700330 constexpr size_t count = 10000;
331
332 for (size_t i = 0; i < count; ++i) {
333 item.setInt32(std::to_string(i).c_str(), i);
334 }
335 for (size_t i = 0; i < count; i += 2) {
336 item.filter(std::to_string(i).c_str()); // filter out all the evens.
337 }
338 for (size_t i = 0; i < count; ++i) {
339 int32_t i32;
340 if (i & 1) { // check to see that only the odds are left.
341 ASSERT_TRUE(item.getInt32(std::to_string(i).c_str(), &i32));
342 ASSERT_EQ((int32_t)i, i32);
343 } else {
344 ASSERT_FALSE(item.getInt32(std::to_string(i).c_str(), &i32));
345 }
346 }
347}
348
Andy Hung3253f2d2019-10-21 14:50:07 -0700349TEST(mediametrics_tests, superbig_item_removal2) {
Ray Essickf27e9872019-12-07 06:28:46 -0800350 mediametrics::Item item("TheOne");
Andy Hung3253f2d2019-10-21 14:50:07 -0700351 constexpr size_t count = 10000;
352
353 for (size_t i = 0; i < count; ++i) {
354 item.setInt32(std::to_string(i).c_str(), i);
355 }
356 static const char *attrs[] = { "1", };
357 item.filterNot(1, attrs);
358
359 for (size_t i = 0; i < count; ++i) {
360 int32_t i32;
361 if (i == 1) { // check to see that there is only one
362 ASSERT_TRUE(item.getInt32(std::to_string(i).c_str(), &i32));
363 ASSERT_EQ((int32_t)i, i32);
364 } else {
365 ASSERT_FALSE(item.getInt32(std::to_string(i).c_str(), &i32));
366 }
367 }
368}
369
Andy Hungaeef7882019-10-18 15:18:14 -0700370TEST(mediametrics_tests, item_transmutation) {
Ray Essickf27e9872019-12-07 06:28:46 -0800371 mediametrics::Item item("Alchemist's Stone");
Andy Hungaeef7882019-10-18 15:18:14 -0700372
373 item.setInt64("convert", 123);
374 int64_t i64;
375 ASSERT_TRUE(item.getInt64("convert", &i64));
376 ASSERT_EQ(123, i64);
377
378 item.addInt32("convert", 2); // changes type of 'convert' from i64 to i32 (and re-init).
379 ASSERT_FALSE(item.getInt64("convert", &i64)); // should be false, no value in i64.
380
381 int32_t i32;
382 ASSERT_TRUE(item.getInt32("convert", &i32)); // check it is i32 and 2 (123 is discarded).
383 ASSERT_EQ(2, i32);
384}
Andy Hung3253f2d2019-10-21 14:50:07 -0700385
386TEST(mediametrics_tests, item_binderization) {
Ray Essickf27e9872019-12-07 06:28:46 -0800387 mediametrics::Item item;
Andy Hung3253f2d2019-10-21 14:50:07 -0700388 item.setInt32("i32", 1)
389 .setInt64("i64", 2)
390 .setDouble("double", 3.1)
391 .setCString("string", "abc")
392 .setRate("rate", 11, 12);
393
394 Parcel p;
395 item.writeToParcel(&p);
396
397 p.setDataPosition(0); // rewind for reading
Ray Essickf27e9872019-12-07 06:28:46 -0800398 mediametrics::Item item2;
Andy Hung3253f2d2019-10-21 14:50:07 -0700399 item2.readFromParcel(p);
400
401 ASSERT_EQ(item, item2);
402}
403
404TEST(mediametrics_tests, item_byteserialization) {
Ray Essickf27e9872019-12-07 06:28:46 -0800405 mediametrics::Item item;
Andy Hung3253f2d2019-10-21 14:50:07 -0700406 item.setInt32("i32", 1)
407 .setInt64("i64", 2)
408 .setDouble("double", 3.1)
409 .setCString("string", "abc")
410 .setRate("rate", 11, 12);
411
412 char *data;
413 size_t length;
414 ASSERT_EQ(0, item.writeToByteString(&data, &length));
415 ASSERT_GT(length, (size_t)0);
416
Ray Essickf27e9872019-12-07 06:28:46 -0800417 mediametrics::Item item2;
Andy Hung3253f2d2019-10-21 14:50:07 -0700418 item2.readFromByteString(data, length);
419
420 printf("item: %s\n", item.toString().c_str());
421 printf("item2: %s\n", item2.toString().c_str());
422 ASSERT_EQ(item, item2);
423
424 free(data);
425}
426
427TEST(mediametrics_tests, item_iteration) {
Ray Essickf27e9872019-12-07 06:28:46 -0800428 mediametrics::Item item;
Andy Hung3253f2d2019-10-21 14:50:07 -0700429 item.setInt32("i32", 1)
430 .setInt64("i64", 2)
431 .setDouble("double", 3.125)
432 .setCString("string", "abc")
433 .setRate("rate", 11, 12);
434
435 int mask = 0;
436 for (auto &prop : item) {
437 const char *name = prop.getName();
438 if (!strcmp(name, "i32")) {
439 int32_t i32;
440 ASSERT_TRUE(prop.get(&i32));
441 ASSERT_EQ(1, i32);
Andy Hung692870b2020-01-02 13:46:06 -0800442 ASSERT_EQ(1, std::get<int32_t>(prop.get()));
Andy Hung3253f2d2019-10-21 14:50:07 -0700443 mask |= 1;
444 } else if (!strcmp(name, "i64")) {
445 int64_t i64;
446 ASSERT_TRUE(prop.get(&i64));
447 ASSERT_EQ(2, i64);
Andy Hung692870b2020-01-02 13:46:06 -0800448 ASSERT_EQ(2, std::get<int64_t>(prop.get()));
Andy Hung3253f2d2019-10-21 14:50:07 -0700449 mask |= 2;
450 } else if (!strcmp(name, "double")) {
451 double d;
452 ASSERT_TRUE(prop.get(&d));
453 ASSERT_EQ(3.125, d);
Andy Hung692870b2020-01-02 13:46:06 -0800454 ASSERT_EQ(3.125, std::get<double>(prop.get()));
Andy Hung3253f2d2019-10-21 14:50:07 -0700455 mask |= 4;
456 } else if (!strcmp(name, "string")) {
Andy Hungb7aadb32019-12-09 19:40:42 -0800457 std::string s;
Andy Hung3253f2d2019-10-21 14:50:07 -0700458 ASSERT_TRUE(prop.get(&s));
Andy Hungb7aadb32019-12-09 19:40:42 -0800459 ASSERT_EQ("abc", s);
Andy Hung692870b2020-01-02 13:46:06 -0800460 ASSERT_EQ(s, std::get<std::string>(prop.get()));
Andy Hung3253f2d2019-10-21 14:50:07 -0700461 mask |= 8;
462 } else if (!strcmp(name, "rate")) {
463 std::pair<int64_t, int64_t> r;
464 ASSERT_TRUE(prop.get(&r));
465 ASSERT_EQ(11, r.first);
466 ASSERT_EQ(12, r.second);
Andy Hung692870b2020-01-02 13:46:06 -0800467 ASSERT_EQ(r, std::get<decltype(r)>(prop.get()));
Andy Hung3253f2d2019-10-21 14:50:07 -0700468 mask |= 16;
469 } else {
470 FAIL();
471 }
472 }
473 ASSERT_EQ(31, mask);
474}
Andy Hung1efc9c62019-12-03 13:43:33 -0800475
476TEST(mediametrics_tests, item_expansion) {
Ray Essickf27e9872019-12-07 06:28:46 -0800477 mediametrics::LogItem<1> item("I");
Andy Hung1efc9c62019-12-03 13:43:33 -0800478 item.set("i32", (int32_t)1)
479 .set("i64", (int64_t)2)
480 .set("double", (double)3.125)
481 .set("string", "abcdefghijklmnopqrstuvwxyz")
482 .set("rate", std::pair<int64_t, int64_t>(11, 12));
483 ASSERT_TRUE(item.updateHeader());
484
Ray Essickf27e9872019-12-07 06:28:46 -0800485 mediametrics::Item item2;
Andy Hung1efc9c62019-12-03 13:43:33 -0800486 item2.readFromByteString(item.getBuffer(), item.getLength());
487 ASSERT_EQ((pid_t)-1, item2.getPid());
488 ASSERT_EQ((uid_t)-1, item2.getUid());
489 int mask = 0;
490 for (auto &prop : item2) {
491 const char *name = prop.getName();
492 if (!strcmp(name, "i32")) {
493 int32_t i32;
494 ASSERT_TRUE(prop.get(&i32));
495 ASSERT_EQ(1, i32);
496 mask |= 1;
497 } else if (!strcmp(name, "i64")) {
498 int64_t i64;
499 ASSERT_TRUE(prop.get(&i64));
500 ASSERT_EQ(2, i64);
501 mask |= 2;
502 } else if (!strcmp(name, "double")) {
503 double d;
504 ASSERT_TRUE(prop.get(&d));
505 ASSERT_EQ(3.125, d);
506 mask |= 4;
507 } else if (!strcmp(name, "string")) {
Andy Hungb7aadb32019-12-09 19:40:42 -0800508 std::string s;
Andy Hung1efc9c62019-12-03 13:43:33 -0800509 ASSERT_TRUE(prop.get(&s));
Andy Hungb7aadb32019-12-09 19:40:42 -0800510 ASSERT_EQ("abcdefghijklmnopqrstuvwxyz", s);
Andy Hung1efc9c62019-12-03 13:43:33 -0800511 mask |= 8;
512 } else if (!strcmp(name, "rate")) {
513 std::pair<int64_t, int64_t> r;
514 ASSERT_TRUE(prop.get(&r));
515 ASSERT_EQ(11, r.first);
516 ASSERT_EQ(12, r.second);
517 mask |= 16;
518 } else {
519 FAIL();
520 }
521 }
522 ASSERT_EQ(31, mask);
523}
524
525TEST(mediametrics_tests, item_expansion2) {
Ray Essickf27e9872019-12-07 06:28:46 -0800526 mediametrics::LogItem<1> item("Bigly");
Andy Hung1efc9c62019-12-03 13:43:33 -0800527 item.setPid(123)
528 .setUid(456);
529 constexpr size_t count = 10000;
530
531 for (size_t i = 0; i < count; ++i) {
532 // printf("recording %zu, %p, len:%zu of %zu remaining:%zu \n", i, item.getBuffer(), item.getLength(), item.getCapacity(), item.getRemaining());
533 item.set(std::to_string(i).c_str(), (int32_t)i);
534 }
535 ASSERT_TRUE(item.updateHeader());
536
Ray Essickf27e9872019-12-07 06:28:46 -0800537 mediametrics::Item item2;
Andy Hung1efc9c62019-12-03 13:43:33 -0800538 printf("begin buffer:%p length:%zu\n", item.getBuffer(), item.getLength());
539 fflush(stdout);
540 item2.readFromByteString(item.getBuffer(), item.getLength());
541
542 ASSERT_EQ((pid_t)123, item2.getPid());
543 ASSERT_EQ((uid_t)456, item2.getUid());
544 for (size_t i = 0; i < count; ++i) {
545 int32_t i32;
546 ASSERT_TRUE(item2.getInt32(std::to_string(i).c_str(), &i32));
547 ASSERT_EQ((int32_t)i, i32);
548 }
549}
Andy Hung06f3aba2019-12-03 16:36:42 -0800550
551TEST(mediametrics_tests, time_machine_storage) {
Ray Essickf27e9872019-12-07 06:28:46 -0800552 auto item = std::make_shared<mediametrics::Item>("Key");
Andy Hung06f3aba2019-12-03 16:36:42 -0800553 (*item).set("i32", (int32_t)1)
554 .set("i64", (int64_t)2)
555 .set("double", (double)3.125)
556 .set("string", "abcdefghijklmnopqrstuvwxyz")
557 .set("rate", std::pair<int64_t, int64_t>(11, 12));
558
559 // Let's put the item in
560 android::mediametrics::TimeMachine timeMachine;
561 ASSERT_EQ(NO_ERROR, timeMachine.put(item, true));
562
563 // Can we read the values?
564 int32_t i32;
565 ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "i32", &i32, -1));
566 ASSERT_EQ(1, i32);
567
568 int64_t i64;
569 ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "i64", &i64, -1));
570 ASSERT_EQ(2, i64);
571
572 double d;
573 ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "double", &d, -1));
574 ASSERT_EQ(3.125, d);
575
576 std::string s;
577 ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "string", &s, -1));
578 ASSERT_EQ("abcdefghijklmnopqrstuvwxyz", s);
579
580 // Using fully qualified name?
581 i32 = 0;
582 ASSERT_EQ(NO_ERROR, timeMachine.get("Key.i32", &i32, -1));
583 ASSERT_EQ(1, i32);
584
585 i64 = 0;
586 ASSERT_EQ(NO_ERROR, timeMachine.get("Key.i64", &i64, -1));
587 ASSERT_EQ(2, i64);
588
589 d = 0.;
590 ASSERT_EQ(NO_ERROR, timeMachine.get("Key.double", &d, -1));
591 ASSERT_EQ(3.125, d);
592
593 s.clear();
594 ASSERT_EQ(NO_ERROR, timeMachine.get("Key.string", &s, -1));
595 ASSERT_EQ("abcdefghijklmnopqrstuvwxyz", s);
596}
597
598TEST(mediametrics_tests, time_machine_remote_key) {
Ray Essickf27e9872019-12-07 06:28:46 -0800599 auto item = std::make_shared<mediametrics::Item>("Key1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800600 (*item).set("one", (int32_t)1)
601 .set("two", (int32_t)2);
602
603 android::mediametrics::TimeMachine timeMachine;
604 ASSERT_EQ(NO_ERROR, timeMachine.put(item, true));
605
Ray Essickf27e9872019-12-07 06:28:46 -0800606 auto item2 = std::make_shared<mediametrics::Item>("Key2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800607 (*item2).set("three", (int32_t)3)
608 .set("[Key1]four", (int32_t)4) // affects Key1
609 .set("[Key1]five", (int32_t)5); // affects key1
610
611 ASSERT_EQ(NO_ERROR, timeMachine.put(item2, true));
612
Ray Essickf27e9872019-12-07 06:28:46 -0800613 auto item3 = std::make_shared<mediametrics::Item>("Key2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800614 (*item3).set("six", (int32_t)6)
615 .set("[Key1]seven", (int32_t)7); // affects Key1
616
617 ASSERT_EQ(NO_ERROR, timeMachine.put(item3, false)); // remote keys not allowed.
618
619 // Can we read the values?
620 int32_t i32;
621 ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.one", &i32, -1));
622 ASSERT_EQ(1, i32);
623
624 ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.two", &i32, -1));
625 ASSERT_EQ(2, i32);
626
627 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.three", &i32, -1));
628
629 ASSERT_EQ(NO_ERROR, timeMachine.get("Key2.three", &i32, -1));
630 ASSERT_EQ(3, i32);
631
632 ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.four", &i32, -1));
633 ASSERT_EQ(4, i32);
634
635 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key2.four", &i32, -1));
636
637 ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.five", &i32, -1));
638 ASSERT_EQ(5, i32);
639
640 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key2.five", &i32, -1));
641
642 ASSERT_EQ(NO_ERROR, timeMachine.get("Key2.six", &i32, -1));
643 ASSERT_EQ(6, i32);
644
645 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key2.seven", &i32, -1));
646}
647
648TEST(mediametrics_tests, time_machine_gc) {
Ray Essickf27e9872019-12-07 06:28:46 -0800649 auto item = std::make_shared<mediametrics::Item>("Key1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800650 (*item).set("one", (int32_t)1)
651 .set("two", (int32_t)2)
652 .setTimestamp(10);
653
654 android::mediametrics::TimeMachine timeMachine(1, 2); // keep at most 2 keys.
655
656 ASSERT_EQ((size_t)0, timeMachine.size());
657
658 ASSERT_EQ(NO_ERROR, timeMachine.put(item, true));
659
660 ASSERT_EQ((size_t)1, timeMachine.size());
661
Ray Essickf27e9872019-12-07 06:28:46 -0800662 auto item2 = std::make_shared<mediametrics::Item>("Key2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800663 (*item2).set("three", (int32_t)3)
664 .set("[Key1]three", (int32_t)3)
665 .setTimestamp(11);
666
667 ASSERT_EQ(NO_ERROR, timeMachine.put(item2, true));
668 ASSERT_EQ((size_t)2, timeMachine.size());
669
670 //printf("Before\n%s\n\n", timeMachine.dump().c_str());
671
Ray Essickf27e9872019-12-07 06:28:46 -0800672 auto item3 = std::make_shared<mediametrics::Item>("Key3");
Andy Hung06f3aba2019-12-03 16:36:42 -0800673 (*item3).set("six", (int32_t)6)
674 .set("[Key1]four", (int32_t)4) // affects Key1
675 .set("[Key1]five", (int32_t)5) // affects key1
676 .setTimestamp(12);
677
678 ASSERT_EQ(NO_ERROR, timeMachine.put(item3, true));
679
680 ASSERT_EQ((size_t)2, timeMachine.size());
681
682 // Can we read the values?
683 int32_t i32;
684 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.one", &i32, -1));
685 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.two", &i32, -1));
686 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.three", &i32, -1));
687 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.four", &i32, -1));
688 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.five", &i32, -1));
689
690 ASSERT_EQ(NO_ERROR, timeMachine.get("Key2.three", &i32, -1));
691 ASSERT_EQ(3, i32);
692
693 ASSERT_EQ(NO_ERROR, timeMachine.get("Key3.six", &i32, -1));
694 ASSERT_EQ(6, i32);
695
696 printf("After\n%s\n", timeMachine.dump().first.c_str());
697}
698
699TEST(mediametrics_tests, transaction_log_gc) {
Ray Essickf27e9872019-12-07 06:28:46 -0800700 auto item = std::make_shared<mediametrics::Item>("Key1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800701 (*item).set("one", (int32_t)1)
702 .set("two", (int32_t)2)
703 .setTimestamp(10);
704
705 android::mediametrics::TransactionLog transactionLog(1, 2); // keep at most 2 items
706 ASSERT_EQ((size_t)0, transactionLog.size());
707
708 ASSERT_EQ(NO_ERROR, transactionLog.put(item));
709 ASSERT_EQ((size_t)1, transactionLog.size());
710
Ray Essickf27e9872019-12-07 06:28:46 -0800711 auto item2 = std::make_shared<mediametrics::Item>("Key2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800712 (*item2).set("three", (int32_t)3)
713 .set("[Key1]three", (int32_t)3)
714 .setTimestamp(11);
715
716 ASSERT_EQ(NO_ERROR, transactionLog.put(item2));
717 ASSERT_EQ((size_t)2, transactionLog.size());
718
Ray Essickf27e9872019-12-07 06:28:46 -0800719 auto item3 = std::make_shared<mediametrics::Item>("Key3");
Andy Hung06f3aba2019-12-03 16:36:42 -0800720 (*item3).set("six", (int32_t)6)
721 .set("[Key1]four", (int32_t)4) // affects Key1
722 .set("[Key1]five", (int32_t)5) // affects key1
723 .setTimestamp(12);
724
725 ASSERT_EQ(NO_ERROR, transactionLog.put(item3));
726 ASSERT_EQ((size_t)2, transactionLog.size());
727}
728
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800729TEST(mediametrics_tests, analytics_actions) {
730 mediametrics::AnalyticsActions analyticsActions;
731 bool action1 = false;
732 bool action2 = false;
733 bool action3 = false;
734 bool action4 = false;
735
736 // check to see whether various actions have been matched.
737 analyticsActions.addAction(
738 "audio.flinger.event",
739 std::string("AudioFlinger"),
740 std::make_shared<mediametrics::AnalyticsActions::Function>(
741 [&](const std::shared_ptr<const android::mediametrics::Item> &) {
742 action1 = true;
743 }));
744
745 analyticsActions.addAction(
746 "audio.*.event",
747 std::string("AudioFlinger"),
748 std::make_shared<mediametrics::AnalyticsActions::Function>(
749 [&](const std::shared_ptr<const android::mediametrics::Item> &) {
750 action2 = true;
751 }));
752
753 analyticsActions.addAction("audio.fl*n*g*r.event",
754 std::string("AudioFlinger"),
755 std::make_shared<mediametrics::AnalyticsActions::Function>(
756 [&](const std::shared_ptr<const android::mediametrics::Item> &) {
757 action3 = true;
758 }));
759
760 analyticsActions.addAction("audio.fl*gn*r.event",
761 std::string("AudioFlinger"),
762 std::make_shared<mediametrics::AnalyticsActions::Function>(
763 [&](const std::shared_ptr<const android::mediametrics::Item> &) {
764 action4 = true;
765 }));
766
767 // make a test item
768 auto item = std::make_shared<mediametrics::Item>("audio.flinger");
769 (*item).set("event", "AudioFlinger");
770
771 // get the actions and execute them
772 auto actions = analyticsActions.getActionsForItem(item);
773 for (const auto& action : actions) {
774 action->operator()(item);
775 }
776
777 // The following should match.
778 ASSERT_EQ(true, action1);
779 ASSERT_EQ(true, action2);
780 ASSERT_EQ(true, action3);
781 ASSERT_EQ(false, action4); // audio.fl*gn*r != audio.flinger
782}
783
Andy Hung06f3aba2019-12-03 16:36:42 -0800784TEST(mediametrics_tests, audio_analytics_permission) {
Ray Essickf27e9872019-12-07 06:28:46 -0800785 auto item = std::make_shared<mediametrics::Item>("audio.1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800786 (*item).set("one", (int32_t)1)
787 .set("two", (int32_t)2)
788 .setTimestamp(10);
789
Ray Essickf27e9872019-12-07 06:28:46 -0800790 auto item2 = std::make_shared<mediametrics::Item>("audio.1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800791 (*item2).set("three", (int32_t)3)
792 .setTimestamp(11);
793
Ray Essickf27e9872019-12-07 06:28:46 -0800794 auto item3 = std::make_shared<mediametrics::Item>("audio.2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800795 (*item3).set("four", (int32_t)4)
796 .setTimestamp(12);
797
798 android::mediametrics::AudioAnalytics audioAnalytics;
799
800 // untrusted entities cannot create a new key.
801 ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item, false /* isTrusted */));
802 ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item2, false /* isTrusted */));
803
804 // TODO: Verify contents of AudioAnalytics.
805 // Currently there is no getter API in AudioAnalytics besides dump.
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800806 ASSERT_EQ(9, audioAnalytics.dump(1000).second /* lines */);
Andy Hung06f3aba2019-12-03 16:36:42 -0800807
808 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item, true /* isTrusted */));
809 // untrusted entities can add to an existing key
810 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item2, false /* isTrusted */));
811
812 // Check that we have some info in the dump.
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800813 ASSERT_LT(9, audioAnalytics.dump(1000).second /* lines */);
Andy Hung06f3aba2019-12-03 16:36:42 -0800814}
815
816TEST(mediametrics_tests, audio_analytics_dump) {
Ray Essickf27e9872019-12-07 06:28:46 -0800817 auto item = std::make_shared<mediametrics::Item>("audio.1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800818 (*item).set("one", (int32_t)1)
819 .set("two", (int32_t)2)
820 .setTimestamp(10);
821
Ray Essickf27e9872019-12-07 06:28:46 -0800822 auto item2 = std::make_shared<mediametrics::Item>("audio.1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800823 (*item2).set("three", (int32_t)3)
824 .setTimestamp(11);
825
Ray Essickf27e9872019-12-07 06:28:46 -0800826 auto item3 = std::make_shared<mediametrics::Item>("audio.2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800827 (*item3).set("four", (int32_t)4)
828 .setTimestamp(12);
829
830 android::mediametrics::AudioAnalytics audioAnalytics;
831
832 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item, true /* isTrusted */));
833 // untrusted entities can add to an existing key
834 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item2, false /* isTrusted */));
835 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item3, true /* isTrusted */));
836
837 // find out how many lines we have.
838 auto [string, lines] = audioAnalytics.dump(1000);
839 ASSERT_EQ(lines, (int32_t) countNewlines(string.c_str()));
840
841 printf("AudioAnalytics: %s", string.c_str());
842 // ensure that dump operates over those lines.
843 for (int32_t ll = 0; ll < lines; ++ll) {
844 auto [s, l] = audioAnalytics.dump(ll);
845 ASSERT_EQ(ll, l);
846 ASSERT_EQ(ll, (int32_t) countNewlines(s.c_str()));
847 }
848}