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 <packagelistparser/packagelistparser.h>
18 
19 #include <memory>
20 
21 #include <android-base/file.h>
22 
23 #include <gtest/gtest.h>
24 
TEST(packagelistparser,smoke)25 TEST(packagelistparser, smoke) {
26   TemporaryFile tf;
27   android::base::WriteStringToFile(
28       // No gids.
29       "com.test.a0 10014 0 /data/user/0/com.test.a0 platform:privapp:targetSdkVersion=19 none\n"
30       // One gid.
31       "com.test.a1 10007 1 /data/user/0/com.test.a1 platform:privapp:targetSdkVersion=21 1023\n"
32       // Multiple gids.
33       "com.test.a2 10011 0 /data/user/0/com.test.a2 media:privapp:targetSdkVersion=30 "
34       "2001,1065,1023,3003,3007,1024\n"
35       // The two new fields (profileable flag and version code).
36       "com.test.a3 10022 0 /data/user/0/com.test.a3 selabel:blah none 1 123\n",
37       tf.path);
38 
39   std::vector<pkg_info*> packages;
40   packagelist_parse_file(
41       tf.path,
42       [](pkg_info* info, void* user_data) -> bool {
43         reinterpret_cast<std::vector<pkg_info*>*>(user_data)->push_back(info);
44         return true;
45       },
46       &packages);
47 
48   ASSERT_EQ(4U, packages.size());
49 
50   ASSERT_STREQ("com.test.a0", packages[0]->name);
51   ASSERT_EQ(10014, packages[0]->uid);
52   ASSERT_FALSE(packages[0]->debuggable);
53   ASSERT_STREQ("/data/user/0/com.test.a0", packages[0]->data_dir);
54   ASSERT_STREQ("platform:privapp:targetSdkVersion=19", packages[0]->seinfo);
55   ASSERT_EQ(0U, packages[0]->gids.cnt);
56   ASSERT_FALSE(packages[0]->profileable_from_shell);
57   ASSERT_EQ(0, packages[0]->version_code);
58 
59   ASSERT_STREQ("com.test.a1", packages[1]->name);
60   ASSERT_EQ(10007, packages[1]->uid);
61   ASSERT_TRUE(packages[1]->debuggable);
62   ASSERT_STREQ("/data/user/0/com.test.a1", packages[1]->data_dir);
63   ASSERT_STREQ("platform:privapp:targetSdkVersion=21", packages[1]->seinfo);
64   ASSERT_EQ(1U, packages[1]->gids.cnt);
65   ASSERT_EQ(1023U, packages[1]->gids.gids[0]);
66   ASSERT_FALSE(packages[0]->profileable_from_shell);
67   ASSERT_EQ(0, packages[0]->version_code);
68 
69   ASSERT_STREQ("com.test.a2", packages[2]->name);
70   ASSERT_EQ(10011, packages[2]->uid);
71   ASSERT_FALSE(packages[2]->debuggable);
72   ASSERT_STREQ("/data/user/0/com.test.a2", packages[2]->data_dir);
73   ASSERT_STREQ("media:privapp:targetSdkVersion=30", packages[2]->seinfo);
74   ASSERT_EQ(6U, packages[2]->gids.cnt);
75   ASSERT_EQ(2001U, packages[2]->gids.gids[0]);
76   ASSERT_EQ(1024U, packages[2]->gids.gids[5]);
77   ASSERT_FALSE(packages[0]->profileable_from_shell);
78   ASSERT_EQ(0, packages[0]->version_code);
79 
80   ASSERT_STREQ("com.test.a3", packages[3]->name);
81   ASSERT_EQ(10022, packages[3]->uid);
82   ASSERT_FALSE(packages[3]->debuggable);
83   ASSERT_STREQ("/data/user/0/com.test.a3", packages[3]->data_dir);
84   ASSERT_STREQ("selabel:blah", packages[3]->seinfo);
85   ASSERT_EQ(0U, packages[3]->gids.cnt);
86   ASSERT_TRUE(packages[3]->profileable_from_shell);
87   ASSERT_EQ(123, packages[3]->version_code);
88 
89   for (auto& package : packages) packagelist_free(package);
90 }
91 
TEST(packagelistparser,early_exit)92 TEST(packagelistparser, early_exit) {
93   TemporaryFile tf;
94   android::base::WriteStringToFile(
95       "com.test.a0 1 0 / a none\n"
96       "com.test.a1 1 0 / a none\n"
97       "com.test.a2 1 0 / a none\n",
98       tf.path);
99 
100   std::vector<pkg_info*> packages;
101   packagelist_parse_file(
102       tf.path,
103       [](pkg_info* info, void* user_data) -> bool {
104         std::vector<pkg_info*>* p = reinterpret_cast<std::vector<pkg_info*>*>(user_data);
105         p->push_back(info);
106         return p->size() < 2;
107       },
108       &packages);
109 
110   ASSERT_EQ(2U, packages.size());
111 
112   ASSERT_STREQ("com.test.a0", packages[0]->name);
113   ASSERT_STREQ("com.test.a1", packages[1]->name);
114 
115   for (auto& package : packages) packagelist_free(package);
116 }
117 
TEST(packagelistparser,system_package_list)118 TEST(packagelistparser, system_package_list) {
119   // Check that we can actually read the packages.list installed on the device.
120   std::vector<pkg_info*> packages;
121   packagelist_parse(
122       [](pkg_info* info, void* user_data) -> bool {
123         reinterpret_cast<std::vector<pkg_info*>*>(user_data)->push_back(info);
124         return true;
125       },
126       &packages);
127   // Not much we can say for sure about what we expect, other than that there
128   // are likely to be lots of packages...
129   ASSERT_GT(packages.size(), 10U);
130 }
131 
TEST(packagelistparser,packagelist_free_nullptr)132 TEST(packagelistparser, packagelist_free_nullptr) {
133   packagelist_free(nullptr);
134 }
135