xref: /aosp_15_r20/system/apex/apexd/apex_database_test.cpp (revision 33f3758387333dbd2962d7edbd98681940d895da)
1*33f37583SAndroid Build Coastguard Worker /*
2*33f37583SAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*33f37583SAndroid Build Coastguard Worker  *
4*33f37583SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*33f37583SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*33f37583SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*33f37583SAndroid Build Coastguard Worker  *
8*33f37583SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*33f37583SAndroid Build Coastguard Worker  *
10*33f37583SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*33f37583SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*33f37583SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*33f37583SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*33f37583SAndroid Build Coastguard Worker  * limitations under the License.
15*33f37583SAndroid Build Coastguard Worker  */
16*33f37583SAndroid Build Coastguard Worker 
17*33f37583SAndroid Build Coastguard Worker #include "apex_database.h"
18*33f37583SAndroid Build Coastguard Worker 
19*33f37583SAndroid Build Coastguard Worker #include <android-base/macros.h>
20*33f37583SAndroid Build Coastguard Worker #include <android-base/result-gmock.h>
21*33f37583SAndroid Build Coastguard Worker #include <gmock/gmock.h>
22*33f37583SAndroid Build Coastguard Worker #include <gtest/gtest.h>
23*33f37583SAndroid Build Coastguard Worker 
24*33f37583SAndroid Build Coastguard Worker #include <string>
25*33f37583SAndroid Build Coastguard Worker #include <tuple>
26*33f37583SAndroid Build Coastguard Worker 
27*33f37583SAndroid Build Coastguard Worker using android::base::Error;
28*33f37583SAndroid Build Coastguard Worker using android::base::Result;
29*33f37583SAndroid Build Coastguard Worker using android::base::testing::HasError;
30*33f37583SAndroid Build Coastguard Worker using android::base::testing::Ok;
31*33f37583SAndroid Build Coastguard Worker using android::base::testing::WithMessage;
32*33f37583SAndroid Build Coastguard Worker 
33*33f37583SAndroid Build Coastguard Worker namespace android {
34*33f37583SAndroid Build Coastguard Worker namespace apex {
35*33f37583SAndroid Build Coastguard Worker namespace {
36*33f37583SAndroid Build Coastguard Worker 
37*33f37583SAndroid Build Coastguard Worker using MountedApexData = MountedApexDatabase::MountedApexData;
38*33f37583SAndroid Build Coastguard Worker 
CountPackages(const MountedApexDatabase & db)39*33f37583SAndroid Build Coastguard Worker size_t CountPackages(const MountedApexDatabase& db) {
40*33f37583SAndroid Build Coastguard Worker   size_t ret = 0;
41*33f37583SAndroid Build Coastguard Worker   db.ForallMountedApexes([&ret](const std::string& a ATTRIBUTE_UNUSED,
42*33f37583SAndroid Build Coastguard Worker                                 const MountedApexData& b ATTRIBUTE_UNUSED,
43*33f37583SAndroid Build Coastguard Worker                                 bool c ATTRIBUTE_UNUSED) { ++ret; });
44*33f37583SAndroid Build Coastguard Worker   return ret;
45*33f37583SAndroid Build Coastguard Worker }
46*33f37583SAndroid Build Coastguard Worker 
Contains(const MountedApexDatabase & db,const std::string & package,const MountedApexData & data)47*33f37583SAndroid Build Coastguard Worker bool Contains(const MountedApexDatabase& db, const std::string& package,
48*33f37583SAndroid Build Coastguard Worker               const MountedApexData& data) {
49*33f37583SAndroid Build Coastguard Worker   bool found = false;
50*33f37583SAndroid Build Coastguard Worker   db.ForallMountedApexes([&](const std::string& p, const MountedApexData& d,
51*33f37583SAndroid Build Coastguard Worker                              bool b ATTRIBUTE_UNUSED) {
52*33f37583SAndroid Build Coastguard Worker     if (package == p && data == d) {
53*33f37583SAndroid Build Coastguard Worker       found = true;
54*33f37583SAndroid Build Coastguard Worker     }
55*33f37583SAndroid Build Coastguard Worker   });
56*33f37583SAndroid Build Coastguard Worker   return found;
57*33f37583SAndroid Build Coastguard Worker }
58*33f37583SAndroid Build Coastguard Worker 
ContainsPackage(const MountedApexDatabase & db,const std::string & package,const MountedApexData & data)59*33f37583SAndroid Build Coastguard Worker bool ContainsPackage(const MountedApexDatabase& db, const std::string& package,
60*33f37583SAndroid Build Coastguard Worker                      const MountedApexData& data) {
61*33f37583SAndroid Build Coastguard Worker   bool found = false;
62*33f37583SAndroid Build Coastguard Worker   db.ForallMountedApexes(
63*33f37583SAndroid Build Coastguard Worker       package, [&](const MountedApexData& d, bool b ATTRIBUTE_UNUSED) {
64*33f37583SAndroid Build Coastguard Worker         if (data == d) {
65*33f37583SAndroid Build Coastguard Worker           found = true;
66*33f37583SAndroid Build Coastguard Worker         }
67*33f37583SAndroid Build Coastguard Worker       });
68*33f37583SAndroid Build Coastguard Worker   return found;
69*33f37583SAndroid Build Coastguard Worker }
70*33f37583SAndroid Build Coastguard Worker 
TEST(ApexDatabaseTest,AddRemovedMountedApex)71*33f37583SAndroid Build Coastguard Worker TEST(ApexDatabaseTest, AddRemovedMountedApex) {
72*33f37583SAndroid Build Coastguard Worker   constexpr const char* kPackage = "package";
73*33f37583SAndroid Build Coastguard Worker   constexpr const char* kLoopName = "loop";
74*33f37583SAndroid Build Coastguard Worker   constexpr const char* kPath = "path";
75*33f37583SAndroid Build Coastguard Worker   constexpr const char* kMountPoint = "mount";
76*33f37583SAndroid Build Coastguard Worker   constexpr const char* kDeviceName = "dev";
77*33f37583SAndroid Build Coastguard Worker 
78*33f37583SAndroid Build Coastguard Worker   MountedApexDatabase db;
79*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(CountPackages(db), 0u);
80*33f37583SAndroid Build Coastguard Worker 
81*33f37583SAndroid Build Coastguard Worker   MountedApexData data(0, kLoopName, kPath, kMountPoint, kDeviceName);
82*33f37583SAndroid Build Coastguard Worker   db.AddMountedApex(kPackage, data);
83*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(Contains(db, kPackage, data));
84*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(ContainsPackage(db, kPackage, data));
85*33f37583SAndroid Build Coastguard Worker 
86*33f37583SAndroid Build Coastguard Worker   db.RemoveMountedApex(kPackage, kPath);
87*33f37583SAndroid Build Coastguard Worker   EXPECT_FALSE(Contains(db, kPackage, data));
88*33f37583SAndroid Build Coastguard Worker   EXPECT_FALSE(ContainsPackage(db, kPackage, data));
89*33f37583SAndroid Build Coastguard Worker }
90*33f37583SAndroid Build Coastguard Worker 
TEST(ApexDatabaseTest,MountMultiple)91*33f37583SAndroid Build Coastguard Worker TEST(ApexDatabaseTest, MountMultiple) {
92*33f37583SAndroid Build Coastguard Worker   constexpr const char* kPackage[] = {"package", "package", "package",
93*33f37583SAndroid Build Coastguard Worker                                       "package"};
94*33f37583SAndroid Build Coastguard Worker   constexpr const char* kLoopName[] = {"loop", "loop2", "loop3", "loop4"};
95*33f37583SAndroid Build Coastguard Worker   constexpr const char* kPath[] = {"path", "path2", "path", "path4"};
96*33f37583SAndroid Build Coastguard Worker   constexpr const char* kMountPoint[] = {"mount", "mount2", "mount", "mount4"};
97*33f37583SAndroid Build Coastguard Worker   constexpr const char* kDeviceName[] = {"dev", "dev2", "dev3", "dev4"};
98*33f37583SAndroid Build Coastguard Worker 
99*33f37583SAndroid Build Coastguard Worker   MountedApexDatabase db;
100*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(CountPackages(db), 0u);
101*33f37583SAndroid Build Coastguard Worker 
102*33f37583SAndroid Build Coastguard Worker   MountedApexData data[arraysize(kPackage)];
103*33f37583SAndroid Build Coastguard Worker   for (size_t i = 0; i < arraysize(kPackage); ++i) {
104*33f37583SAndroid Build Coastguard Worker     data[i] = MountedApexData(0, kLoopName[i], kPath[i], kMountPoint[i],
105*33f37583SAndroid Build Coastguard Worker                               kDeviceName[i]);
106*33f37583SAndroid Build Coastguard Worker     db.AddMountedApex(kPackage[i], data[i]);
107*33f37583SAndroid Build Coastguard Worker   }
108*33f37583SAndroid Build Coastguard Worker 
109*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(CountPackages(db), 4u);
110*33f37583SAndroid Build Coastguard Worker   for (size_t i = 0; i < arraysize(kPackage); ++i) {
111*33f37583SAndroid Build Coastguard Worker     ASSERT_TRUE(Contains(db, kPackage[i], data[i]));
112*33f37583SAndroid Build Coastguard Worker     ASSERT_TRUE(ContainsPackage(db, kPackage[i], data[i]));
113*33f37583SAndroid Build Coastguard Worker   }
114*33f37583SAndroid Build Coastguard Worker 
115*33f37583SAndroid Build Coastguard Worker   db.RemoveMountedApex(kPackage[0], kPath[0]);
116*33f37583SAndroid Build Coastguard Worker   EXPECT_FALSE(Contains(db, kPackage[0], data[0]));
117*33f37583SAndroid Build Coastguard Worker   EXPECT_FALSE(ContainsPackage(db, kPackage[0], data[0]));
118*33f37583SAndroid Build Coastguard Worker   EXPECT_TRUE(Contains(db, kPackage[1], data[1]));
119*33f37583SAndroid Build Coastguard Worker   EXPECT_TRUE(ContainsPackage(db, kPackage[1], data[1]));
120*33f37583SAndroid Build Coastguard Worker   EXPECT_TRUE(Contains(db, kPackage[2], data[2]));
121*33f37583SAndroid Build Coastguard Worker   EXPECT_TRUE(ContainsPackage(db, kPackage[2], data[2]));
122*33f37583SAndroid Build Coastguard Worker   EXPECT_TRUE(Contains(db, kPackage[3], data[3]));
123*33f37583SAndroid Build Coastguard Worker   EXPECT_TRUE(ContainsPackage(db, kPackage[3], data[3]));
124*33f37583SAndroid Build Coastguard Worker }
125*33f37583SAndroid Build Coastguard Worker 
TEST(ApexDatabaseTest,DoIfLatest)126*33f37583SAndroid Build Coastguard Worker TEST(ApexDatabaseTest, DoIfLatest) {
127*33f37583SAndroid Build Coastguard Worker   // Check by passing error-returning handler
128*33f37583SAndroid Build Coastguard Worker   // When handler is triggered, DoIfLatest() returns the expected error.
129*33f37583SAndroid Build Coastguard Worker   auto returnError = []() -> Result<void> { return Error() << "expected"; };
130*33f37583SAndroid Build Coastguard Worker 
131*33f37583SAndroid Build Coastguard Worker   MountedApexDatabase db;
132*33f37583SAndroid Build Coastguard Worker 
133*33f37583SAndroid Build Coastguard Worker   // With apex: [{version=0,path=path}]
134*33f37583SAndroid Build Coastguard Worker   db.AddMountedApex("package", 0, "loop", "path", "mount", "dev");
135*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(db.DoIfLatest("package", "path", returnError),
136*33f37583SAndroid Build Coastguard Worker               HasError(WithMessage("expected")));
137*33f37583SAndroid Build Coastguard Worker 
138*33f37583SAndroid Build Coastguard Worker   // With apexes: [{version=0,path=path}, {version=5,path=path5}]
139*33f37583SAndroid Build Coastguard Worker   db.AddMountedApex("package", 5, "loop5", "path5", "mount5", "dev5");
140*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(db.DoIfLatest("package", "path", returnError), Ok());
141*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(db.DoIfLatest("package", "path5", returnError),
142*33f37583SAndroid Build Coastguard Worker               HasError(WithMessage("expected")));
143*33f37583SAndroid Build Coastguard Worker }
144*33f37583SAndroid Build Coastguard Worker 
TEST(ApexDatabaseTest,GetLatestMountedApex)145*33f37583SAndroid Build Coastguard Worker TEST(ApexDatabaseTest, GetLatestMountedApex) {
146*33f37583SAndroid Build Coastguard Worker   constexpr const char* kPackage = "package";
147*33f37583SAndroid Build Coastguard Worker   constexpr const char* kLoopName = "loop";
148*33f37583SAndroid Build Coastguard Worker   constexpr const char* kPath = "path";
149*33f37583SAndroid Build Coastguard Worker   constexpr const char* kMountPoint = "mount";
150*33f37583SAndroid Build Coastguard Worker   constexpr const char* kDeviceName = "dev";
151*33f37583SAndroid Build Coastguard Worker 
152*33f37583SAndroid Build Coastguard Worker   MountedApexDatabase db;
153*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(CountPackages(db), 0u);
154*33f37583SAndroid Build Coastguard Worker 
155*33f37583SAndroid Build Coastguard Worker   MountedApexData data(0, kLoopName, kPath, kMountPoint, kDeviceName);
156*33f37583SAndroid Build Coastguard Worker   db.AddMountedApex(kPackage, data);
157*33f37583SAndroid Build Coastguard Worker 
158*33f37583SAndroid Build Coastguard Worker   auto ret = db.GetLatestMountedApex(kPackage);
159*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(ret.has_value());
160*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(ret.value(), data);
161*33f37583SAndroid Build Coastguard Worker }
162*33f37583SAndroid Build Coastguard Worker 
TEST(ApexDatabaseTest,GetLatestMountedApexReturnsNullopt)163*33f37583SAndroid Build Coastguard Worker TEST(ApexDatabaseTest, GetLatestMountedApexReturnsNullopt) {
164*33f37583SAndroid Build Coastguard Worker   MountedApexDatabase db;
165*33f37583SAndroid Build Coastguard Worker   auto ret = db.GetLatestMountedApex("no-such-name");
166*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(ret.has_value());
167*33f37583SAndroid Build Coastguard Worker }
168*33f37583SAndroid Build Coastguard Worker 
169*33f37583SAndroid Build Coastguard Worker #pragma clang diagnostic push
170*33f37583SAndroid Build Coastguard Worker // error: 'ReturnSentinel' was marked unused but was used
171*33f37583SAndroid Build Coastguard Worker // [-Werror,-Wused-but-marked-unused]
172*33f37583SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wused-but-marked-unused"
173*33f37583SAndroid Build Coastguard Worker 
TEST(MountedApexDataTest,NoDuplicateLoopDataLoopDevices)174*33f37583SAndroid Build Coastguard Worker TEST(MountedApexDataTest, NoDuplicateLoopDataLoopDevices) {
175*33f37583SAndroid Build Coastguard Worker   ASSERT_DEATH(
176*33f37583SAndroid Build Coastguard Worker       {
177*33f37583SAndroid Build Coastguard Worker         MountedApexDatabase db;
178*33f37583SAndroid Build Coastguard Worker         db.AddMountedApex("package", 0, "loop", "path", "mount", "dm");
179*33f37583SAndroid Build Coastguard Worker         db.AddMountedApex("package2", 0, "loop", "path2", "mount2", "dm2");
180*33f37583SAndroid Build Coastguard Worker       },
181*33f37583SAndroid Build Coastguard Worker       "Duplicate loop device: loop");
182*33f37583SAndroid Build Coastguard Worker }
183*33f37583SAndroid Build Coastguard Worker 
TEST(MountedApexDataTest,NoDuplicateDm)184*33f37583SAndroid Build Coastguard Worker TEST(MountedApexDataTest, NoDuplicateDm) {
185*33f37583SAndroid Build Coastguard Worker   ASSERT_DEATH(
186*33f37583SAndroid Build Coastguard Worker       {
187*33f37583SAndroid Build Coastguard Worker         MountedApexDatabase db;
188*33f37583SAndroid Build Coastguard Worker         db.AddMountedApex("package", 0, "loop", "path", "mount", "dm");
189*33f37583SAndroid Build Coastguard Worker         db.AddMountedApex("package2", 0, "loop2", "path2", "mount2", "dm");
190*33f37583SAndroid Build Coastguard Worker       },
191*33f37583SAndroid Build Coastguard Worker       "Duplicate dm device: dm");
192*33f37583SAndroid Build Coastguard Worker }
193*33f37583SAndroid Build Coastguard Worker 
194*33f37583SAndroid Build Coastguard Worker #pragma clang diagnostic pop
195*33f37583SAndroid Build Coastguard Worker 
196*33f37583SAndroid Build Coastguard Worker }  // namespace
197*33f37583SAndroid Build Coastguard Worker }  // namespace apex
198*33f37583SAndroid Build Coastguard Worker }  // namespace android
199