1 /*
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 #include "src/traced/probes/packages_list/packages_list_data_source.h"
18 
19 #include <stdio.h>
20 
21 #include <set>
22 #include <string>
23 
24 #include "perfetto/ext/base/pipe.h"
25 #include "perfetto/protozero/scattered_heap_buffer.h"
26 #include "protos/perfetto/trace/android/packages_list.gen.h"
27 #include "protos/perfetto/trace/android/packages_list.pbzero.h"
28 #include "src/traced/probes/packages_list/packages_list_parser.h"
29 #include "test/gtest_and_gmock.h"
30 
31 namespace perfetto {
32 namespace {
33 
TEST(PackagesListDataSourceTest,ParseLineNonProfileNonDebug)34 TEST(PackagesListDataSourceTest, ParseLineNonProfileNonDebug) {
35   char kLine[] =
36       "com.test.app 1234 0 /data/user/0/com.test.app "
37       "default:targetSdkVersion=12452 1234,5678 0 1111\n";
38   Package pkg;
39   ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg));
40   EXPECT_EQ(pkg.name, "com.test.app");
41   EXPECT_EQ(pkg.debuggable, false);
42   EXPECT_EQ(pkg.profileable_from_shell, false);
43   EXPECT_EQ(pkg.version_code, 1111);
44 }
45 
TEST(PackagesListDataSourceTest,ParseLineProfileNonDebug)46 TEST(PackagesListDataSourceTest, ParseLineProfileNonDebug) {
47   char kLine[] =
48       "com.test.app 1234 0 /data/user/0/com.test.app "
49       "default:targetSdkVersion=12452 1234,5678 1 1111\n";
50   Package pkg;
51   ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg));
52   EXPECT_EQ(pkg.name, "com.test.app");
53   EXPECT_EQ(pkg.debuggable, false);
54   EXPECT_EQ(pkg.profileable_from_shell, true);
55   EXPECT_EQ(pkg.version_code, 1111);
56 }
57 
TEST(PackagesListDataSourceTest,ParseLineNonProfileDebug)58 TEST(PackagesListDataSourceTest, ParseLineNonProfileDebug) {
59   char kLine[] =
60       "com.test.app 1234 1 /data/user/0/com.test.app "
61       "default:targetSdkVersion=12452 1234,5678 0 1111\n";
62   Package pkg;
63   ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg));
64   EXPECT_EQ(pkg.name, "com.test.app");
65   EXPECT_EQ(pkg.debuggable, true);
66   EXPECT_EQ(pkg.profileable_from_shell, false);
67   EXPECT_EQ(pkg.version_code, 1111);
68 }
69 
TEST(PackagesListDataSourceTest,ParseLineProfileDebug)70 TEST(PackagesListDataSourceTest, ParseLineProfileDebug) {
71   char kLine[] =
72       "com.test.app 1234 1 /data/user/0/com.test.app "
73       "default:targetSdkVersion=12452 1234,5678 1 1111\n";
74   Package pkg;
75   ASSERT_TRUE(ReadPackagesListLine(kLine, &pkg));
76   EXPECT_EQ(pkg.name, "com.test.app");
77   EXPECT_EQ(pkg.debuggable, true);
78   EXPECT_EQ(pkg.profileable_from_shell, true);
79   EXPECT_EQ(pkg.version_code, 1111);
80 }
81 
TEST(PackagesListDataSourceTest,EmptyNameFilterIncludesAll)82 TEST(PackagesListDataSourceTest, EmptyNameFilterIncludesAll) {
83   char buf[] =
84       "com.test.one 1000 0 /data/user/0/com.test.one "
85       "default:targetSdkVersion=10 none 0 10\n"
86       "com.test.two 1001 0 /data/user/0/com.test.two "
87       "default:targetSdkVersion=10 1065,3002 0 20\n"
88       "com.test.three 1002 0 /data/user/0/com.test.three "
89       "default:targetSdkVersion=10 1065,3002 0 30\n";
90 
91   // Create a stream from |buf|, up to the null byte. Avoid fmemopen as it
92   // requires a higher target API (23) than we use for portability.
93   auto pipe = base::Pipe::Create();
94   PERFETTO_CHECK(write(pipe.wr.get(), buf, sizeof(buf) - 1) == sizeof(buf) - 1);
95   pipe.wr.reset();
96   auto fs = base::ScopedFstream(fdopen(pipe.rd.get(), "r"));
97   pipe.rd.release();  // now owned by |fs|
98 
99   protozero::HeapBuffered<protos::pbzero::PackagesList> packages_list;
100   std::set<std::string> filter{};
101 
102   ASSERT_TRUE(ParsePackagesListStream(packages_list.get(), fs, filter));
103 
104   protos::gen::PackagesList parsed_list;
105   parsed_list.ParseFromString(packages_list.SerializeAsString());
106 
107   EXPECT_FALSE(parsed_list.read_error());
108   EXPECT_FALSE(parsed_list.parse_error());
109   // all entries
110   EXPECT_EQ(parsed_list.packages_size(), 3);
111   EXPECT_EQ(parsed_list.packages()[0].name(), "com.test.one");
112   EXPECT_EQ(parsed_list.packages()[0].version_code(), 10);
113   EXPECT_EQ(parsed_list.packages()[1].name(), "com.test.two");
114   EXPECT_EQ(parsed_list.packages()[1].version_code(), 20);
115   EXPECT_EQ(parsed_list.packages()[2].name(), "com.test.three");
116   EXPECT_EQ(parsed_list.packages()[2].version_code(), 30);
117 }
118 
TEST(PackagesListDataSourceTest,NameFilter)119 TEST(PackagesListDataSourceTest, NameFilter) {
120   char buf[] =
121       "com.test.one 1000 0 /data/user/0/com.test.one "
122       "default:targetSdkVersion=10 none 0 10\n"
123       "com.test.two 1001 0 /data/user/0/com.test.two "
124       "default:targetSdkVersion=10 1065,3002 0 20\n"
125       "com.test.three 1002 0 /data/user/0/com.test.three "
126       "default:targetSdkVersion=10 1065,3002 0 30\n";
127 
128   // Create a stream from |buf|, up to the null byte. Avoid fmemopen as it
129   // requires a higher target API (23) than we use for portability.
130   auto pipe = base::Pipe::Create();
131   PERFETTO_CHECK(write(pipe.wr.get(), buf, sizeof(buf) - 1) == sizeof(buf) - 1);
132   pipe.wr.reset();
133   auto fs = base::ScopedFstream(fdopen(pipe.rd.get(), "r"));
134   pipe.rd.release();  // now owned by |fs|
135 
136   protozero::HeapBuffered<protos::pbzero::PackagesList> packages_list;
137   std::set<std::string> filter{"com.test.one", "com.test.three"};
138 
139   ASSERT_TRUE(ParsePackagesListStream(packages_list.get(), fs, filter));
140 
141   protos::gen::PackagesList parsed_list;
142   parsed_list.ParseFromString(packages_list.SerializeAsString());
143 
144   EXPECT_FALSE(parsed_list.read_error());
145   EXPECT_FALSE(parsed_list.parse_error());
146   // two named entries
147   EXPECT_EQ(parsed_list.packages_size(), 2);
148   EXPECT_EQ(parsed_list.packages()[0].name(), "com.test.one");
149   EXPECT_EQ(parsed_list.packages()[0].version_code(), 10);
150   EXPECT_EQ(parsed_list.packages()[1].name(), "com.test.three");
151   EXPECT_EQ(parsed_list.packages()[1].version_code(), 30);
152 }
153 
154 }  // namespace
155 }  // namespace perfetto
156