blob: dea625c65ad0a519805c72efbcb24a01ab7c35b1 [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
115 // Use Thunk to check whether we have the lock when calling a method through LockWrap.
116
117 class Thunk {
118 std::function<void()> mF;
119
120 public:
121 Thunk(decltype(mF) f) : mF(f) {}
122 void thunk() { mF(); }
123 };
124
125 android::mediametrics::LockWrap<Thunk> s4([&]{
126 ASSERT_EQ(true, s4.isLocked()); // we must be locked when thunk() is called.
127 });
128
129 // This will fail if we are not locked during method access.
130 s4->thunk();
131}
132
133TEST(mediametrics_tests, lock_wrap_multithread) {
134 class Accumulator {
135 int32_t value_ = 0;
136 public:
137 void add(int32_t incr) {
138 const int32_t temp = value_;
139 sleep(0); // yield
140 value_ = temp + incr;
141 }
142 int32_t get() { return value_; }
143 };
144
145 android::mediametrics::LockWrap<Accumulator> a{}; // locked accumulator succeeds
146 // auto a = std::make_shared<Accumulator>(); // this fails, only 50% adds atomic.
147
148 constexpr size_t THREADS = 100;
149 constexpr size_t ITERATIONS = 10;
150 constexpr int32_t INCREMENT = 1;
151
152 std::vector<std::future<void>> threads(THREADS);
153 for (size_t i = 0; i < THREADS; ++i) {
154 threads.push_back(std::async(std::launch::async, [&] {
155 for (size_t j = 0; j < ITERATIONS; ++j) {
156 a->add(INCREMENT);
157 }
158 }));
159 }
160 threads.clear();
161
162 // If the add operations are not atomic, value will be smaller than expected.
163 ASSERT_EQ(INCREMENT * THREADS * ITERATIONS, (size_t)a->get());
164}
165
Andy Hungc89c8dc2019-10-16 17:48:21 -0700166TEST(mediametrics_tests, instantiate) {
Ray Essickf27e9872019-12-07 06:28:46 -0800167 sp mediaMetrics = new MediaMetricsService();
Andy Hungc89c8dc2019-10-16 17:48:21 -0700168 status_t status;
169
Andy Hungc89c8dc2019-10-16 17:48:21 -0700170 // random keys ignored when empty
Ray Essickf27e9872019-12-07 06:28:46 -0800171 std::unique_ptr<mediametrics::Item> random_key(mediametrics::Item::create("random_key"));
Andy Hunga87e69c2019-10-18 10:07:40 -0700172 status = mediaMetrics->submit(random_key.get());
173 ASSERT_EQ(PERMISSION_DENIED, status);
Andy Hungc89c8dc2019-10-16 17:48:21 -0700174
175 // random keys ignored with data
Andy Hungc89c8dc2019-10-16 17:48:21 -0700176 random_key->setInt32("foo", 10);
Andy Hunga87e69c2019-10-18 10:07:40 -0700177 status = mediaMetrics->submit(random_key.get());
178 ASSERT_EQ(PERMISSION_DENIED, status);
Andy Hungc89c8dc2019-10-16 17:48:21 -0700179
180 // known keys ignored if empty
Ray Essickf27e9872019-12-07 06:28:46 -0800181 std::unique_ptr<mediametrics::Item> audiotrack_key(mediametrics::Item::create("audiotrack"));
Andy Hunga87e69c2019-10-18 10:07:40 -0700182 status = mediaMetrics->submit(audiotrack_key.get());
183 ASSERT_EQ(BAD_VALUE, status);
Andy Hungc89c8dc2019-10-16 17:48:21 -0700184
Andy Hunga87e69c2019-10-18 10:07:40 -0700185 // known keys not ignored if not empty
186 audiotrack_key->addInt32("foo", 10);
187 status = mediaMetrics->submit(audiotrack_key.get());
188 ASSERT_EQ(NO_ERROR, status);
Andy Hungc89c8dc2019-10-16 17:48:21 -0700189
Andy Hungaeef7882019-10-18 15:18:14 -0700190
191 /*
192 // fluent style that goes directly to mediametrics
Ray Essickf27e9872019-12-07 06:28:46 -0800193 ASSERT_EQ(true, mediametrics::Item("audiorecord")
Andy Hungaeef7882019-10-18 15:18:14 -0700194 .setInt32("value", 2)
195 .addInt32("bar", 1)
196 .addInt32("value", 3)
197 .selfrecord());
198 */
199
Andy Hungc89c8dc2019-10-16 17:48:21 -0700200 mediaMetrics->dump(fileno(stdout), {} /* args */);
201}
Andy Hungaeef7882019-10-18 15:18:14 -0700202
Andy Hunga85efab2019-12-23 11:41:29 -0800203TEST(mediametrics_tests, package_installer_check) {
204 ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
205 "abcd", "installer")); // ok, package name has no dot.
206 ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
207 "android.com", "installer")); // ok, package name starts with android
208
209 ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
210 "abc.def", "com.android.foo")); // ok, installer name starts with com.android
211 ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
212 "123.456", "com.google.bar")); // ok, installer name starts with com.google
213 ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
214 "r2.d2", "preload")); // ok, installer name is preload
215
216 ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
217 "abc.def", "installer")); // unknown installer
218 ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
219 "123.456", "installer")); // unknown installer
220 ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
221 "r2.d2", "preload23")); // unknown installer
222
223 ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
224 "com.android.foo", "abc.def")); // unknown installer
225 ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
226 "com.google.bar", "123.456")); // unknown installer
227}
228
Andy Hungaeef7882019-10-18 15:18:14 -0700229TEST(mediametrics_tests, item_manipulation) {
Ray Essickf27e9872019-12-07 06:28:46 -0800230 mediametrics::Item item("audiorecord");
Andy Hungaeef7882019-10-18 15:18:14 -0700231
232 item.setInt32("value", 2).addInt32("bar", 3).addInt32("value", 4);
233
234 int32_t i32;
235 ASSERT_TRUE(item.getInt32("value", &i32));
236 ASSERT_EQ(6, i32);
237
238 ASSERT_TRUE(item.getInt32("bar", &i32));
239 ASSERT_EQ(3, i32);
240
241 item.setInt64("big", INT64_MAX).setInt64("smaller", INT64_MAX - 1).addInt64("smaller", -2);
242
243 int64_t i64;
244 ASSERT_TRUE(item.getInt64("big", &i64));
245 ASSERT_EQ(INT64_MAX, i64);
246
247 ASSERT_TRUE(item.getInt64("smaller", &i64));
248 ASSERT_EQ(INT64_MAX - 3, i64);
249
250 item.setDouble("precise", 10.5).setDouble("small", 0.125).addDouble("precise", 0.25);
251
252 double d;
253 ASSERT_TRUE(item.getDouble("precise", &d));
254 ASSERT_EQ(10.75, d);
255
256 ASSERT_TRUE(item.getDouble("small", &d));
257 ASSERT_EQ(0.125, d);
258
259 char *s;
260 item.setCString("name", "Frank").setCString("mother", "June").setCString("mother", "July");
261 ASSERT_TRUE(item.getCString("name", &s));
262 ASSERT_EQ(0, strcmp(s, "Frank"));
263 free(s);
264
265 ASSERT_TRUE(item.getCString("mother", &s));
266 ASSERT_EQ(0, strcmp(s, "July")); // "July" overwrites "June"
267 free(s);
268
269 item.setRate("burgersPerHour", 5, 2);
270 int64_t b, h;
271 ASSERT_TRUE(item.getRate("burgersPerHour", &b, &h, &d));
272 ASSERT_EQ(5, b);
273 ASSERT_EQ(2, h);
274 ASSERT_EQ(2.5, d);
275
276 item.addRate("burgersPerHour", 4, 2);
277 ASSERT_TRUE(item.getRate("burgersPerHour", &b, &h, &d));
278 ASSERT_EQ(9, b);
279 ASSERT_EQ(4, h);
280 ASSERT_EQ(2.25, d);
281
282 printf("item: %s\n", item.toString().c_str());
283 fflush(stdout);
284
Ray Essickf27e9872019-12-07 06:28:46 -0800285 sp mediaMetrics = new MediaMetricsService();
Andy Hungaeef7882019-10-18 15:18:14 -0700286 status_t status = mediaMetrics->submit(&item);
287 ASSERT_EQ(NO_ERROR, status);
288 mediaMetrics->dump(fileno(stdout), {} /* args */);
289}
290
291TEST(mediametrics_tests, superbig_item) {
Ray Essickf27e9872019-12-07 06:28:46 -0800292 mediametrics::Item item("TheBigOne");
Andy Hungaeef7882019-10-18 15:18:14 -0700293 constexpr size_t count = 10000;
294
295 for (size_t i = 0; i < count; ++i) {
296 item.setInt32(std::to_string(i).c_str(), i);
297 }
298 for (size_t i = 0; i < count; ++i) {
299 int32_t i32;
300 ASSERT_TRUE(item.getInt32(std::to_string(i).c_str(), &i32));
301 ASSERT_EQ((int32_t)i, i32);
302 }
303}
304
305TEST(mediametrics_tests, superbig_item_removal) {
Ray Essickf27e9872019-12-07 06:28:46 -0800306 mediametrics::Item item("TheOddBigOne");
Andy Hungaeef7882019-10-18 15:18:14 -0700307 constexpr size_t count = 10000;
308
309 for (size_t i = 0; i < count; ++i) {
310 item.setInt32(std::to_string(i).c_str(), i);
311 }
312 for (size_t i = 0; i < count; i += 2) {
313 item.filter(std::to_string(i).c_str()); // filter out all the evens.
314 }
315 for (size_t i = 0; i < count; ++i) {
316 int32_t i32;
317 if (i & 1) { // check to see that only the odds are left.
318 ASSERT_TRUE(item.getInt32(std::to_string(i).c_str(), &i32));
319 ASSERT_EQ((int32_t)i, i32);
320 } else {
321 ASSERT_FALSE(item.getInt32(std::to_string(i).c_str(), &i32));
322 }
323 }
324}
325
Andy Hung3253f2d2019-10-21 14:50:07 -0700326TEST(mediametrics_tests, superbig_item_removal2) {
Ray Essickf27e9872019-12-07 06:28:46 -0800327 mediametrics::Item item("TheOne");
Andy Hung3253f2d2019-10-21 14:50:07 -0700328 constexpr size_t count = 10000;
329
330 for (size_t i = 0; i < count; ++i) {
331 item.setInt32(std::to_string(i).c_str(), i);
332 }
333 static const char *attrs[] = { "1", };
334 item.filterNot(1, attrs);
335
336 for (size_t i = 0; i < count; ++i) {
337 int32_t i32;
338 if (i == 1) { // check to see that there is only one
339 ASSERT_TRUE(item.getInt32(std::to_string(i).c_str(), &i32));
340 ASSERT_EQ((int32_t)i, i32);
341 } else {
342 ASSERT_FALSE(item.getInt32(std::to_string(i).c_str(), &i32));
343 }
344 }
345}
346
Andy Hungaeef7882019-10-18 15:18:14 -0700347TEST(mediametrics_tests, item_transmutation) {
Ray Essickf27e9872019-12-07 06:28:46 -0800348 mediametrics::Item item("Alchemist's Stone");
Andy Hungaeef7882019-10-18 15:18:14 -0700349
350 item.setInt64("convert", 123);
351 int64_t i64;
352 ASSERT_TRUE(item.getInt64("convert", &i64));
353 ASSERT_EQ(123, i64);
354
355 item.addInt32("convert", 2); // changes type of 'convert' from i64 to i32 (and re-init).
356 ASSERT_FALSE(item.getInt64("convert", &i64)); // should be false, no value in i64.
357
358 int32_t i32;
359 ASSERT_TRUE(item.getInt32("convert", &i32)); // check it is i32 and 2 (123 is discarded).
360 ASSERT_EQ(2, i32);
361}
Andy Hung3253f2d2019-10-21 14:50:07 -0700362
363TEST(mediametrics_tests, item_binderization) {
Ray Essickf27e9872019-12-07 06:28:46 -0800364 mediametrics::Item item;
Andy Hung3253f2d2019-10-21 14:50:07 -0700365 item.setInt32("i32", 1)
366 .setInt64("i64", 2)
367 .setDouble("double", 3.1)
368 .setCString("string", "abc")
369 .setRate("rate", 11, 12);
370
371 Parcel p;
372 item.writeToParcel(&p);
373
374 p.setDataPosition(0); // rewind for reading
Ray Essickf27e9872019-12-07 06:28:46 -0800375 mediametrics::Item item2;
Andy Hung3253f2d2019-10-21 14:50:07 -0700376 item2.readFromParcel(p);
377
378 ASSERT_EQ(item, item2);
379}
380
381TEST(mediametrics_tests, item_byteserialization) {
Ray Essickf27e9872019-12-07 06:28:46 -0800382 mediametrics::Item item;
Andy Hung3253f2d2019-10-21 14:50:07 -0700383 item.setInt32("i32", 1)
384 .setInt64("i64", 2)
385 .setDouble("double", 3.1)
386 .setCString("string", "abc")
387 .setRate("rate", 11, 12);
388
389 char *data;
390 size_t length;
391 ASSERT_EQ(0, item.writeToByteString(&data, &length));
392 ASSERT_GT(length, (size_t)0);
393
Ray Essickf27e9872019-12-07 06:28:46 -0800394 mediametrics::Item item2;
Andy Hung3253f2d2019-10-21 14:50:07 -0700395 item2.readFromByteString(data, length);
396
397 printf("item: %s\n", item.toString().c_str());
398 printf("item2: %s\n", item2.toString().c_str());
399 ASSERT_EQ(item, item2);
400
401 free(data);
402}
403
404TEST(mediametrics_tests, item_iteration) {
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.125)
409 .setCString("string", "abc")
410 .setRate("rate", 11, 12);
411
412 int mask = 0;
413 for (auto &prop : item) {
414 const char *name = prop.getName();
415 if (!strcmp(name, "i32")) {
416 int32_t i32;
417 ASSERT_TRUE(prop.get(&i32));
418 ASSERT_EQ(1, i32);
Andy Hung692870b2020-01-02 13:46:06 -0800419 ASSERT_EQ(1, std::get<int32_t>(prop.get()));
Andy Hung3253f2d2019-10-21 14:50:07 -0700420 mask |= 1;
421 } else if (!strcmp(name, "i64")) {
422 int64_t i64;
423 ASSERT_TRUE(prop.get(&i64));
424 ASSERT_EQ(2, i64);
Andy Hung692870b2020-01-02 13:46:06 -0800425 ASSERT_EQ(2, std::get<int64_t>(prop.get()));
Andy Hung3253f2d2019-10-21 14:50:07 -0700426 mask |= 2;
427 } else if (!strcmp(name, "double")) {
428 double d;
429 ASSERT_TRUE(prop.get(&d));
430 ASSERT_EQ(3.125, d);
Andy Hung692870b2020-01-02 13:46:06 -0800431 ASSERT_EQ(3.125, std::get<double>(prop.get()));
Andy Hung3253f2d2019-10-21 14:50:07 -0700432 mask |= 4;
433 } else if (!strcmp(name, "string")) {
Andy Hungb7aadb32019-12-09 19:40:42 -0800434 std::string s;
Andy Hung3253f2d2019-10-21 14:50:07 -0700435 ASSERT_TRUE(prop.get(&s));
Andy Hungb7aadb32019-12-09 19:40:42 -0800436 ASSERT_EQ("abc", s);
Andy Hung692870b2020-01-02 13:46:06 -0800437 ASSERT_EQ(s, std::get<std::string>(prop.get()));
Andy Hung3253f2d2019-10-21 14:50:07 -0700438 mask |= 8;
439 } else if (!strcmp(name, "rate")) {
440 std::pair<int64_t, int64_t> r;
441 ASSERT_TRUE(prop.get(&r));
442 ASSERT_EQ(11, r.first);
443 ASSERT_EQ(12, r.second);
Andy Hung692870b2020-01-02 13:46:06 -0800444 ASSERT_EQ(r, std::get<decltype(r)>(prop.get()));
Andy Hung3253f2d2019-10-21 14:50:07 -0700445 mask |= 16;
446 } else {
447 FAIL();
448 }
449 }
450 ASSERT_EQ(31, mask);
451}
Andy Hung1efc9c62019-12-03 13:43:33 -0800452
453TEST(mediametrics_tests, item_expansion) {
Ray Essickf27e9872019-12-07 06:28:46 -0800454 mediametrics::LogItem<1> item("I");
Andy Hung1efc9c62019-12-03 13:43:33 -0800455 item.set("i32", (int32_t)1)
456 .set("i64", (int64_t)2)
457 .set("double", (double)3.125)
458 .set("string", "abcdefghijklmnopqrstuvwxyz")
459 .set("rate", std::pair<int64_t, int64_t>(11, 12));
460 ASSERT_TRUE(item.updateHeader());
461
Ray Essickf27e9872019-12-07 06:28:46 -0800462 mediametrics::Item item2;
Andy Hung1efc9c62019-12-03 13:43:33 -0800463 item2.readFromByteString(item.getBuffer(), item.getLength());
464 ASSERT_EQ((pid_t)-1, item2.getPid());
465 ASSERT_EQ((uid_t)-1, item2.getUid());
466 int mask = 0;
467 for (auto &prop : item2) {
468 const char *name = prop.getName();
469 if (!strcmp(name, "i32")) {
470 int32_t i32;
471 ASSERT_TRUE(prop.get(&i32));
472 ASSERT_EQ(1, i32);
473 mask |= 1;
474 } else if (!strcmp(name, "i64")) {
475 int64_t i64;
476 ASSERT_TRUE(prop.get(&i64));
477 ASSERT_EQ(2, i64);
478 mask |= 2;
479 } else if (!strcmp(name, "double")) {
480 double d;
481 ASSERT_TRUE(prop.get(&d));
482 ASSERT_EQ(3.125, d);
483 mask |= 4;
484 } else if (!strcmp(name, "string")) {
Andy Hungb7aadb32019-12-09 19:40:42 -0800485 std::string s;
Andy Hung1efc9c62019-12-03 13:43:33 -0800486 ASSERT_TRUE(prop.get(&s));
Andy Hungb7aadb32019-12-09 19:40:42 -0800487 ASSERT_EQ("abcdefghijklmnopqrstuvwxyz", s);
Andy Hung1efc9c62019-12-03 13:43:33 -0800488 mask |= 8;
489 } else if (!strcmp(name, "rate")) {
490 std::pair<int64_t, int64_t> r;
491 ASSERT_TRUE(prop.get(&r));
492 ASSERT_EQ(11, r.first);
493 ASSERT_EQ(12, r.second);
494 mask |= 16;
495 } else {
496 FAIL();
497 }
498 }
499 ASSERT_EQ(31, mask);
500}
501
502TEST(mediametrics_tests, item_expansion2) {
Ray Essickf27e9872019-12-07 06:28:46 -0800503 mediametrics::LogItem<1> item("Bigly");
Andy Hung1efc9c62019-12-03 13:43:33 -0800504 item.setPid(123)
505 .setUid(456);
506 constexpr size_t count = 10000;
507
508 for (size_t i = 0; i < count; ++i) {
509 // printf("recording %zu, %p, len:%zu of %zu remaining:%zu \n", i, item.getBuffer(), item.getLength(), item.getCapacity(), item.getRemaining());
510 item.set(std::to_string(i).c_str(), (int32_t)i);
511 }
512 ASSERT_TRUE(item.updateHeader());
513
Ray Essickf27e9872019-12-07 06:28:46 -0800514 mediametrics::Item item2;
Andy Hung1efc9c62019-12-03 13:43:33 -0800515 printf("begin buffer:%p length:%zu\n", item.getBuffer(), item.getLength());
516 fflush(stdout);
517 item2.readFromByteString(item.getBuffer(), item.getLength());
518
519 ASSERT_EQ((pid_t)123, item2.getPid());
520 ASSERT_EQ((uid_t)456, item2.getUid());
521 for (size_t i = 0; i < count; ++i) {
522 int32_t i32;
523 ASSERT_TRUE(item2.getInt32(std::to_string(i).c_str(), &i32));
524 ASSERT_EQ((int32_t)i, i32);
525 }
526}
Andy Hung06f3aba2019-12-03 16:36:42 -0800527
528TEST(mediametrics_tests, time_machine_storage) {
Ray Essickf27e9872019-12-07 06:28:46 -0800529 auto item = std::make_shared<mediametrics::Item>("Key");
Andy Hung06f3aba2019-12-03 16:36:42 -0800530 (*item).set("i32", (int32_t)1)
531 .set("i64", (int64_t)2)
532 .set("double", (double)3.125)
533 .set("string", "abcdefghijklmnopqrstuvwxyz")
534 .set("rate", std::pair<int64_t, int64_t>(11, 12));
535
536 // Let's put the item in
537 android::mediametrics::TimeMachine timeMachine;
538 ASSERT_EQ(NO_ERROR, timeMachine.put(item, true));
539
540 // Can we read the values?
541 int32_t i32;
542 ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "i32", &i32, -1));
543 ASSERT_EQ(1, i32);
544
545 int64_t i64;
546 ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "i64", &i64, -1));
547 ASSERT_EQ(2, i64);
548
549 double d;
550 ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "double", &d, -1));
551 ASSERT_EQ(3.125, d);
552
553 std::string s;
554 ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "string", &s, -1));
555 ASSERT_EQ("abcdefghijklmnopqrstuvwxyz", s);
556
557 // Using fully qualified name?
558 i32 = 0;
559 ASSERT_EQ(NO_ERROR, timeMachine.get("Key.i32", &i32, -1));
560 ASSERT_EQ(1, i32);
561
562 i64 = 0;
563 ASSERT_EQ(NO_ERROR, timeMachine.get("Key.i64", &i64, -1));
564 ASSERT_EQ(2, i64);
565
566 d = 0.;
567 ASSERT_EQ(NO_ERROR, timeMachine.get("Key.double", &d, -1));
568 ASSERT_EQ(3.125, d);
569
570 s.clear();
571 ASSERT_EQ(NO_ERROR, timeMachine.get("Key.string", &s, -1));
572 ASSERT_EQ("abcdefghijklmnopqrstuvwxyz", s);
573}
574
575TEST(mediametrics_tests, time_machine_remote_key) {
Ray Essickf27e9872019-12-07 06:28:46 -0800576 auto item = std::make_shared<mediametrics::Item>("Key1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800577 (*item).set("one", (int32_t)1)
578 .set("two", (int32_t)2);
579
580 android::mediametrics::TimeMachine timeMachine;
581 ASSERT_EQ(NO_ERROR, timeMachine.put(item, true));
582
Ray Essickf27e9872019-12-07 06:28:46 -0800583 auto item2 = std::make_shared<mediametrics::Item>("Key2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800584 (*item2).set("three", (int32_t)3)
585 .set("[Key1]four", (int32_t)4) // affects Key1
586 .set("[Key1]five", (int32_t)5); // affects key1
587
588 ASSERT_EQ(NO_ERROR, timeMachine.put(item2, true));
589
Ray Essickf27e9872019-12-07 06:28:46 -0800590 auto item3 = std::make_shared<mediametrics::Item>("Key2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800591 (*item3).set("six", (int32_t)6)
592 .set("[Key1]seven", (int32_t)7); // affects Key1
593
594 ASSERT_EQ(NO_ERROR, timeMachine.put(item3, false)); // remote keys not allowed.
595
596 // Can we read the values?
597 int32_t i32;
598 ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.one", &i32, -1));
599 ASSERT_EQ(1, i32);
600
601 ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.two", &i32, -1));
602 ASSERT_EQ(2, i32);
603
604 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.three", &i32, -1));
605
606 ASSERT_EQ(NO_ERROR, timeMachine.get("Key2.three", &i32, -1));
607 ASSERT_EQ(3, i32);
608
609 ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.four", &i32, -1));
610 ASSERT_EQ(4, i32);
611
612 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key2.four", &i32, -1));
613
614 ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.five", &i32, -1));
615 ASSERT_EQ(5, i32);
616
617 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key2.five", &i32, -1));
618
619 ASSERT_EQ(NO_ERROR, timeMachine.get("Key2.six", &i32, -1));
620 ASSERT_EQ(6, i32);
621
622 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key2.seven", &i32, -1));
623}
624
625TEST(mediametrics_tests, time_machine_gc) {
Ray Essickf27e9872019-12-07 06:28:46 -0800626 auto item = std::make_shared<mediametrics::Item>("Key1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800627 (*item).set("one", (int32_t)1)
628 .set("two", (int32_t)2)
629 .setTimestamp(10);
630
631 android::mediametrics::TimeMachine timeMachine(1, 2); // keep at most 2 keys.
632
633 ASSERT_EQ((size_t)0, timeMachine.size());
634
635 ASSERT_EQ(NO_ERROR, timeMachine.put(item, true));
636
637 ASSERT_EQ((size_t)1, timeMachine.size());
638
Ray Essickf27e9872019-12-07 06:28:46 -0800639 auto item2 = std::make_shared<mediametrics::Item>("Key2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800640 (*item2).set("three", (int32_t)3)
641 .set("[Key1]three", (int32_t)3)
642 .setTimestamp(11);
643
644 ASSERT_EQ(NO_ERROR, timeMachine.put(item2, true));
645 ASSERT_EQ((size_t)2, timeMachine.size());
646
647 //printf("Before\n%s\n\n", timeMachine.dump().c_str());
648
Ray Essickf27e9872019-12-07 06:28:46 -0800649 auto item3 = std::make_shared<mediametrics::Item>("Key3");
Andy Hung06f3aba2019-12-03 16:36:42 -0800650 (*item3).set("six", (int32_t)6)
651 .set("[Key1]four", (int32_t)4) // affects Key1
652 .set("[Key1]five", (int32_t)5) // affects key1
653 .setTimestamp(12);
654
655 ASSERT_EQ(NO_ERROR, timeMachine.put(item3, true));
656
657 ASSERT_EQ((size_t)2, timeMachine.size());
658
659 // Can we read the values?
660 int32_t i32;
661 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.one", &i32, -1));
662 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.two", &i32, -1));
663 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.three", &i32, -1));
664 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.four", &i32, -1));
665 ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.five", &i32, -1));
666
667 ASSERT_EQ(NO_ERROR, timeMachine.get("Key2.three", &i32, -1));
668 ASSERT_EQ(3, i32);
669
670 ASSERT_EQ(NO_ERROR, timeMachine.get("Key3.six", &i32, -1));
671 ASSERT_EQ(6, i32);
672
673 printf("After\n%s\n", timeMachine.dump().first.c_str());
674}
675
676TEST(mediametrics_tests, transaction_log_gc) {
Ray Essickf27e9872019-12-07 06:28:46 -0800677 auto item = std::make_shared<mediametrics::Item>("Key1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800678 (*item).set("one", (int32_t)1)
679 .set("two", (int32_t)2)
680 .setTimestamp(10);
681
682 android::mediametrics::TransactionLog transactionLog(1, 2); // keep at most 2 items
683 ASSERT_EQ((size_t)0, transactionLog.size());
684
685 ASSERT_EQ(NO_ERROR, transactionLog.put(item));
686 ASSERT_EQ((size_t)1, transactionLog.size());
687
Ray Essickf27e9872019-12-07 06:28:46 -0800688 auto item2 = std::make_shared<mediametrics::Item>("Key2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800689 (*item2).set("three", (int32_t)3)
690 .set("[Key1]three", (int32_t)3)
691 .setTimestamp(11);
692
693 ASSERT_EQ(NO_ERROR, transactionLog.put(item2));
694 ASSERT_EQ((size_t)2, transactionLog.size());
695
Ray Essickf27e9872019-12-07 06:28:46 -0800696 auto item3 = std::make_shared<mediametrics::Item>("Key3");
Andy Hung06f3aba2019-12-03 16:36:42 -0800697 (*item3).set("six", (int32_t)6)
698 .set("[Key1]four", (int32_t)4) // affects Key1
699 .set("[Key1]five", (int32_t)5) // affects key1
700 .setTimestamp(12);
701
702 ASSERT_EQ(NO_ERROR, transactionLog.put(item3));
703 ASSERT_EQ((size_t)2, transactionLog.size());
704}
705
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800706TEST(mediametrics_tests, analytics_actions) {
707 mediametrics::AnalyticsActions analyticsActions;
708 bool action1 = false;
709 bool action2 = false;
710 bool action3 = false;
711 bool action4 = false;
712
713 // check to see whether various actions have been matched.
714 analyticsActions.addAction(
715 "audio.flinger.event",
716 std::string("AudioFlinger"),
717 std::make_shared<mediametrics::AnalyticsActions::Function>(
718 [&](const std::shared_ptr<const android::mediametrics::Item> &) {
719 action1 = true;
720 }));
721
722 analyticsActions.addAction(
723 "audio.*.event",
724 std::string("AudioFlinger"),
725 std::make_shared<mediametrics::AnalyticsActions::Function>(
726 [&](const std::shared_ptr<const android::mediametrics::Item> &) {
727 action2 = true;
728 }));
729
730 analyticsActions.addAction("audio.fl*n*g*r.event",
731 std::string("AudioFlinger"),
732 std::make_shared<mediametrics::AnalyticsActions::Function>(
733 [&](const std::shared_ptr<const android::mediametrics::Item> &) {
734 action3 = true;
735 }));
736
737 analyticsActions.addAction("audio.fl*gn*r.event",
738 std::string("AudioFlinger"),
739 std::make_shared<mediametrics::AnalyticsActions::Function>(
740 [&](const std::shared_ptr<const android::mediametrics::Item> &) {
741 action4 = true;
742 }));
743
744 // make a test item
745 auto item = std::make_shared<mediametrics::Item>("audio.flinger");
746 (*item).set("event", "AudioFlinger");
747
748 // get the actions and execute them
749 auto actions = analyticsActions.getActionsForItem(item);
750 for (const auto& action : actions) {
751 action->operator()(item);
752 }
753
754 // The following should match.
755 ASSERT_EQ(true, action1);
756 ASSERT_EQ(true, action2);
757 ASSERT_EQ(true, action3);
758 ASSERT_EQ(false, action4); // audio.fl*gn*r != audio.flinger
759}
760
Andy Hung06f3aba2019-12-03 16:36:42 -0800761TEST(mediametrics_tests, audio_analytics_permission) {
Ray Essickf27e9872019-12-07 06:28:46 -0800762 auto item = std::make_shared<mediametrics::Item>("audio.1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800763 (*item).set("one", (int32_t)1)
764 .set("two", (int32_t)2)
765 .setTimestamp(10);
766
Ray Essickf27e9872019-12-07 06:28:46 -0800767 auto item2 = std::make_shared<mediametrics::Item>("audio.1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800768 (*item2).set("three", (int32_t)3)
769 .setTimestamp(11);
770
Ray Essickf27e9872019-12-07 06:28:46 -0800771 auto item3 = std::make_shared<mediametrics::Item>("audio.2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800772 (*item3).set("four", (int32_t)4)
773 .setTimestamp(12);
774
775 android::mediametrics::AudioAnalytics audioAnalytics;
776
777 // untrusted entities cannot create a new key.
778 ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item, false /* isTrusted */));
779 ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item2, false /* isTrusted */));
780
781 // TODO: Verify contents of AudioAnalytics.
782 // Currently there is no getter API in AudioAnalytics besides dump.
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800783 ASSERT_EQ(9, audioAnalytics.dump(1000).second /* lines */);
Andy Hung06f3aba2019-12-03 16:36:42 -0800784
785 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item, true /* isTrusted */));
786 // untrusted entities can add to an existing key
787 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item2, false /* isTrusted */));
788
789 // Check that we have some info in the dump.
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800790 ASSERT_LT(9, audioAnalytics.dump(1000).second /* lines */);
Andy Hung06f3aba2019-12-03 16:36:42 -0800791}
792
793TEST(mediametrics_tests, audio_analytics_dump) {
Ray Essickf27e9872019-12-07 06:28:46 -0800794 auto item = std::make_shared<mediametrics::Item>("audio.1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800795 (*item).set("one", (int32_t)1)
796 .set("two", (int32_t)2)
797 .setTimestamp(10);
798
Ray Essickf27e9872019-12-07 06:28:46 -0800799 auto item2 = std::make_shared<mediametrics::Item>("audio.1");
Andy Hung06f3aba2019-12-03 16:36:42 -0800800 (*item2).set("three", (int32_t)3)
801 .setTimestamp(11);
802
Ray Essickf27e9872019-12-07 06:28:46 -0800803 auto item3 = std::make_shared<mediametrics::Item>("audio.2");
Andy Hung06f3aba2019-12-03 16:36:42 -0800804 (*item3).set("four", (int32_t)4)
805 .setTimestamp(12);
806
807 android::mediametrics::AudioAnalytics audioAnalytics;
808
809 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item, true /* isTrusted */));
810 // untrusted entities can add to an existing key
811 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item2, false /* isTrusted */));
812 ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item3, true /* isTrusted */));
813
814 // find out how many lines we have.
815 auto [string, lines] = audioAnalytics.dump(1000);
816 ASSERT_EQ(lines, (int32_t) countNewlines(string.c_str()));
817
818 printf("AudioAnalytics: %s", string.c_str());
819 // ensure that dump operates over those lines.
820 for (int32_t ll = 0; ll < lines; ++ll) {
821 auto [s, l] = audioAnalytics.dump(ll);
822 ASSERT_EQ(ll, l);
823 ASSERT_EQ(ll, (int32_t) countNewlines(s.c_str()));
824 }
825}