| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "src/traced/probes/packages_list/packages_list_data_source.h" |
| |
| #include <stdio.h> |
| |
| #include <set> |
| #include <string> |
| |
| #include "perfetto/ext/base/pipe.h" |
| #include "perfetto/protozero/scattered_heap_buffer.h" |
| #include "protos/perfetto/trace/android/packages_list.gen.h" |
| #include "protos/perfetto/trace/android/packages_list.pbzero.h" |
| #include "src/traced/probes/packages_list/packages_list_parser.h" |
| #include "test/gtest_and_gmock.h" |
| |
| namespace perfetto { |
| namespace { |
| |
| TEST(PackagesListDataSourceTest, ParseLineNonProfileNonDebug) { |
| char kLine[] = |
| "com.test.app 1234 0 /data/user/0/com.test.app " |
| "default:targetSdkVersion=12452 1234,5678 0 1111\n"; |
| Package pkg; |
| ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg)); |
| EXPECT_EQ(pkg.name, "com.test.app"); |
| EXPECT_EQ(pkg.debuggable, false); |
| EXPECT_EQ(pkg.profileable_from_shell, false); |
| EXPECT_EQ(pkg.version_code, 1111); |
| } |
| |
| TEST(PackagesListDataSourceTest, ParseLineProfileNonDebug) { |
| char kLine[] = |
| "com.test.app 1234 0 /data/user/0/com.test.app " |
| "default:targetSdkVersion=12452 1234,5678 1 1111\n"; |
| Package pkg; |
| ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg)); |
| EXPECT_EQ(pkg.name, "com.test.app"); |
| EXPECT_EQ(pkg.debuggable, false); |
| EXPECT_EQ(pkg.profileable_from_shell, true); |
| EXPECT_EQ(pkg.version_code, 1111); |
| } |
| |
| TEST(PackagesListDataSourceTest, ParseLineNonProfileDebug) { |
| char kLine[] = |
| "com.test.app 1234 1 /data/user/0/com.test.app " |
| "default:targetSdkVersion=12452 1234,5678 0 1111\n"; |
| Package pkg; |
| ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg)); |
| EXPECT_EQ(pkg.name, "com.test.app"); |
| EXPECT_EQ(pkg.debuggable, true); |
| EXPECT_EQ(pkg.profileable_from_shell, false); |
| EXPECT_EQ(pkg.version_code, 1111); |
| } |
| |
| TEST(PackagesListDataSourceTest, ParseLineProfileDebug) { |
| char kLine[] = |
| "com.test.app 1234 1 /data/user/0/com.test.app " |
| "default:targetSdkVersion=12452 1234,5678 1 1111\n"; |
| Package pkg; |
| ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg)); |
| EXPECT_EQ(pkg.name, "com.test.app"); |
| EXPECT_EQ(pkg.debuggable, true); |
| EXPECT_EQ(pkg.profileable_from_shell, true); |
| EXPECT_EQ(pkg.version_code, 1111); |
| } |
| |
| TEST(PackagesListDataSourceTest, EmptyNameFilterIncludesAll) { |
| char buf[] = |
| "com.test.one 1000 0 /data/user/0/com.test.one " |
| "default:targetSdkVersion=10 none 0 10\n" |
| "com.test.two 1001 0 /data/user/0/com.test.two " |
| "default:targetSdkVersion=10 1065,3002 0 20\n" |
| "com.test.three 1002 0 /data/user/0/com.test.three " |
| "default:targetSdkVersion=10 1065,3002 0 30\n"; |
| |
| // Create a stream from |buf|, up to the null byte. Avoid fmemopen as it |
| // requires a higher target API (23) than we use for portability. |
| auto pipe = base::Pipe::Create(); |
| PERFETTO_CHECK(write(pipe.wr.get(), buf, sizeof(buf) - 1) == sizeof(buf) - 1); |
| pipe.wr.reset(); |
| auto fs = base::ScopedFstream(fdopen(pipe.rd.get(), "r")); |
| pipe.rd.release(); // now owned by |fs| |
| |
| protozero::HeapBuffered<protos::pbzero::PackagesList> packages_list; |
| std::set<std::string> filter{}; |
| |
| ASSERT_TRUE(ParsePackagesListStream(packages_list.get(), fs, filter)); |
| |
| protos::gen::PackagesList parsed_list; |
| parsed_list.ParseFromString(packages_list.SerializeAsString()); |
| |
| EXPECT_FALSE(parsed_list.read_error()); |
| EXPECT_FALSE(parsed_list.parse_error()); |
| // all entries |
| EXPECT_EQ(parsed_list.packages_size(), 3); |
| EXPECT_EQ(parsed_list.packages()[0].name(), "com.test.one"); |
| EXPECT_EQ(parsed_list.packages()[0].version_code(), 10); |
| EXPECT_EQ(parsed_list.packages()[1].name(), "com.test.two"); |
| EXPECT_EQ(parsed_list.packages()[1].version_code(), 20); |
| EXPECT_EQ(parsed_list.packages()[2].name(), "com.test.three"); |
| EXPECT_EQ(parsed_list.packages()[2].version_code(), 30); |
| } |
| |
| TEST(PackagesListDataSourceTest, NameFilter) { |
| char buf[] = |
| "com.test.one 1000 0 /data/user/0/com.test.one " |
| "default:targetSdkVersion=10 none 0 10\n" |
| "com.test.two 1001 0 /data/user/0/com.test.two " |
| "default:targetSdkVersion=10 1065,3002 0 20\n" |
| "com.test.three 1002 0 /data/user/0/com.test.three " |
| "default:targetSdkVersion=10 1065,3002 0 30\n"; |
| |
| // Create a stream from |buf|, up to the null byte. Avoid fmemopen as it |
| // requires a higher target API (23) than we use for portability. |
| auto pipe = base::Pipe::Create(); |
| PERFETTO_CHECK(write(pipe.wr.get(), buf, sizeof(buf) - 1) == sizeof(buf) - 1); |
| pipe.wr.reset(); |
| auto fs = base::ScopedFstream(fdopen(pipe.rd.get(), "r")); |
| pipe.rd.release(); // now owned by |fs| |
| |
| protozero::HeapBuffered<protos::pbzero::PackagesList> packages_list; |
| std::set<std::string> filter{"com.test.one", "com.test.three"}; |
| |
| ASSERT_TRUE(ParsePackagesListStream(packages_list.get(), fs, filter)); |
| |
| protos::gen::PackagesList parsed_list; |
| parsed_list.ParseFromString(packages_list.SerializeAsString()); |
| |
| EXPECT_FALSE(parsed_list.read_error()); |
| EXPECT_FALSE(parsed_list.parse_error()); |
| // two named entries |
| EXPECT_EQ(parsed_list.packages_size(), 2); |
| EXPECT_EQ(parsed_list.packages()[0].name(), "com.test.one"); |
| EXPECT_EQ(parsed_list.packages()[0].version_code(), 10); |
| EXPECT_EQ(parsed_list.packages()[1].name(), "com.test.three"); |
| EXPECT_EQ(parsed_list.packages()[1].version_code(), 30); |
| } |
| |
| } // namespace |
| } // namespace perfetto |