xref: /aosp_15_r20/system/apex/apexd/apexservice_test.cpp (revision 33f3758387333dbd2962d7edbd98681940d895da)
1*33f37583SAndroid Build Coastguard Worker /*
2*33f37583SAndroid Build Coastguard Worker  * Copyright (C) 2018 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 <android-base/file.h>
18*33f37583SAndroid Build Coastguard Worker #include <android-base/logging.h>
19*33f37583SAndroid Build Coastguard Worker #include <android-base/macros.h>
20*33f37583SAndroid Build Coastguard Worker #include <android-base/properties.h>
21*33f37583SAndroid Build Coastguard Worker #include <android-base/result-gmock.h>
22*33f37583SAndroid Build Coastguard Worker #include <android-base/scopeguard.h>
23*33f37583SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
24*33f37583SAndroid Build Coastguard Worker #include <android-base/strings.h>
25*33f37583SAndroid Build Coastguard Worker #include <android/apex/ApexInfo.h>
26*33f37583SAndroid Build Coastguard Worker #include <android/apex/IApexService.h>
27*33f37583SAndroid Build Coastguard Worker #include <android/os/IVold.h>
28*33f37583SAndroid Build Coastguard Worker #include <binder/IServiceManager.h>
29*33f37583SAndroid Build Coastguard Worker #include <fs_mgr_overlayfs.h>
30*33f37583SAndroid Build Coastguard Worker #include <fstab/fstab.h>
31*33f37583SAndroid Build Coastguard Worker #include <gmock/gmock.h>
32*33f37583SAndroid Build Coastguard Worker #include <grp.h>
33*33f37583SAndroid Build Coastguard Worker #include <gtest/gtest.h>
34*33f37583SAndroid Build Coastguard Worker #include <libdm/dm.h>
35*33f37583SAndroid Build Coastguard Worker #include <linux/loop.h>
36*33f37583SAndroid Build Coastguard Worker #include <selinux/selinux.h>
37*33f37583SAndroid Build Coastguard Worker #include <stdio.h>
38*33f37583SAndroid Build Coastguard Worker #include <sys/ioctl.h>
39*33f37583SAndroid Build Coastguard Worker #include <sys/stat.h>
40*33f37583SAndroid Build Coastguard Worker #include <sys/types.h>
41*33f37583SAndroid Build Coastguard Worker #include <sys/xattr.h>
42*33f37583SAndroid Build Coastguard Worker 
43*33f37583SAndroid Build Coastguard Worker #include <algorithm>
44*33f37583SAndroid Build Coastguard Worker #include <filesystem>
45*33f37583SAndroid Build Coastguard Worker #include <fstream>
46*33f37583SAndroid Build Coastguard Worker #include <functional>
47*33f37583SAndroid Build Coastguard Worker #include <memory>
48*33f37583SAndroid Build Coastguard Worker #include <optional>
49*33f37583SAndroid Build Coastguard Worker #include <string>
50*33f37583SAndroid Build Coastguard Worker #include <unordered_set>
51*33f37583SAndroid Build Coastguard Worker #include <vector>
52*33f37583SAndroid Build Coastguard Worker 
53*33f37583SAndroid Build Coastguard Worker #include "apex_constants.h"
54*33f37583SAndroid Build Coastguard Worker #include "apex_database.h"
55*33f37583SAndroid Build Coastguard Worker #include "apex_file.h"
56*33f37583SAndroid Build Coastguard Worker #include "apex_manifest.h"
57*33f37583SAndroid Build Coastguard Worker #include "apexd.h"
58*33f37583SAndroid Build Coastguard Worker #include "apexd_private.h"
59*33f37583SAndroid Build Coastguard Worker #include "apexd_session.h"
60*33f37583SAndroid Build Coastguard Worker #include "apexd_test_utils.h"
61*33f37583SAndroid Build Coastguard Worker #include "apexd_utils.h"
62*33f37583SAndroid Build Coastguard Worker #include "session_state.pb.h"
63*33f37583SAndroid Build Coastguard Worker #include "string_log.h"
64*33f37583SAndroid Build Coastguard Worker 
65*33f37583SAndroid Build Coastguard Worker using apex::proto::SessionState;
66*33f37583SAndroid Build Coastguard Worker 
67*33f37583SAndroid Build Coastguard Worker namespace android {
68*33f37583SAndroid Build Coastguard Worker namespace apex {
69*33f37583SAndroid Build Coastguard Worker 
70*33f37583SAndroid Build Coastguard Worker using android::sp;
71*33f37583SAndroid Build Coastguard Worker using android::String16;
72*33f37583SAndroid Build Coastguard Worker using android::apex::testing::CreateSessionInfo;
73*33f37583SAndroid Build Coastguard Worker using android::apex::testing::IsOk;
74*33f37583SAndroid Build Coastguard Worker using android::apex::testing::SessionInfoEq;
75*33f37583SAndroid Build Coastguard Worker using android::base::EndsWith;
76*33f37583SAndroid Build Coastguard Worker using android::base::Error;
77*33f37583SAndroid Build Coastguard Worker using android::base::Join;
78*33f37583SAndroid Build Coastguard Worker using android::base::Result;
79*33f37583SAndroid Build Coastguard Worker using android::base::SetProperty;
80*33f37583SAndroid Build Coastguard Worker using android::base::StartsWith;
81*33f37583SAndroid Build Coastguard Worker using android::base::StringPrintf;
82*33f37583SAndroid Build Coastguard Worker using android::base::unique_fd;
83*33f37583SAndroid Build Coastguard Worker using android::base::testing::Ok;
84*33f37583SAndroid Build Coastguard Worker using android::dm::DeviceMapper;
85*33f37583SAndroid Build Coastguard Worker using ::apex::proto::ApexManifest;
86*33f37583SAndroid Build Coastguard Worker using ::apex::proto::SessionState;
87*33f37583SAndroid Build Coastguard Worker using ::testing::EndsWith;
88*33f37583SAndroid Build Coastguard Worker using ::testing::Not;
89*33f37583SAndroid Build Coastguard Worker using ::testing::SizeIs;
90*33f37583SAndroid Build Coastguard Worker using ::testing::UnorderedElementsAre;
91*33f37583SAndroid Build Coastguard Worker using ::testing::UnorderedElementsAreArray;
92*33f37583SAndroid Build Coastguard Worker 
93*33f37583SAndroid Build Coastguard Worker using MountedApexData = MountedApexDatabase::MountedApexData;
94*33f37583SAndroid Build Coastguard Worker 
95*33f37583SAndroid Build Coastguard Worker namespace fs = std::filesystem;
96*33f37583SAndroid Build Coastguard Worker 
97*33f37583SAndroid Build Coastguard Worker class ApexServiceTest : public ::testing::Test {
98*33f37583SAndroid Build Coastguard Worker  public:
ApexServiceTest()99*33f37583SAndroid Build Coastguard Worker   ApexServiceTest() {}
100*33f37583SAndroid Build Coastguard Worker 
101*33f37583SAndroid Build Coastguard Worker  protected:
SetUp()102*33f37583SAndroid Build Coastguard Worker   void SetUp() override {
103*33f37583SAndroid Build Coastguard Worker     // Enable VERBOSE logging to simplifying debugging
104*33f37583SAndroid Build Coastguard Worker     SetProperty("log.tag.apexd", "VERBOSE");
105*33f37583SAndroid Build Coastguard Worker 
106*33f37583SAndroid Build Coastguard Worker     using android::IBinder;
107*33f37583SAndroid Build Coastguard Worker     using android::IServiceManager;
108*33f37583SAndroid Build Coastguard Worker 
109*33f37583SAndroid Build Coastguard Worker     sp<IServiceManager> sm = android::defaultServiceManager();
110*33f37583SAndroid Build Coastguard Worker     sp<IBinder> binder = sm->waitForService(String16("apexservice"));
111*33f37583SAndroid Build Coastguard Worker     if (binder != nullptr) {
112*33f37583SAndroid Build Coastguard Worker       service_ = android::interface_cast<IApexService>(binder);
113*33f37583SAndroid Build Coastguard Worker     }
114*33f37583SAndroid Build Coastguard Worker     binder = sm->getService(String16("vold"));
115*33f37583SAndroid Build Coastguard Worker     if (binder != nullptr) {
116*33f37583SAndroid Build Coastguard Worker       vold_service_ = android::interface_cast<android::os::IVold>(binder);
117*33f37583SAndroid Build Coastguard Worker     }
118*33f37583SAndroid Build Coastguard Worker 
119*33f37583SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, service_.get());
120*33f37583SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, vold_service_.get());
121*33f37583SAndroid Build Coastguard Worker     android::binder::Status status =
122*33f37583SAndroid Build Coastguard Worker         vold_service_->supportsCheckpoint(&supports_fs_checkpointing_);
123*33f37583SAndroid Build Coastguard Worker     ASSERT_TRUE(IsOk(status));
124*33f37583SAndroid Build Coastguard Worker     CleanUp();
125*33f37583SAndroid Build Coastguard Worker     service_->recollectPreinstalledData();
126*33f37583SAndroid Build Coastguard Worker 
127*33f37583SAndroid Build Coastguard Worker     session_manager_ = ApexSessionManager::Create(GetSessionsDir());
128*33f37583SAndroid Build Coastguard Worker   }
129*33f37583SAndroid Build Coastguard Worker 
TearDown()130*33f37583SAndroid Build Coastguard Worker   void TearDown() override { CleanUp(); }
131*33f37583SAndroid Build Coastguard Worker 
CreateSession(int session_id)132*33f37583SAndroid Build Coastguard Worker   Result<ApexSession> CreateSession(int session_id) {
133*33f37583SAndroid Build Coastguard Worker     return session_manager_->CreateSession(session_id);
134*33f37583SAndroid Build Coastguard Worker   }
135*33f37583SAndroid Build Coastguard Worker 
GetSession(int session_id)136*33f37583SAndroid Build Coastguard Worker   Result<ApexSession> GetSession(int session_id) {
137*33f37583SAndroid Build Coastguard Worker     return session_manager_->GetSession(session_id);
138*33f37583SAndroid Build Coastguard Worker   }
139*33f37583SAndroid Build Coastguard Worker 
GetTestDataDir()140*33f37583SAndroid Build Coastguard Worker   static std::string GetTestDataDir() {
141*33f37583SAndroid Build Coastguard Worker     return android::base::GetExecutableDirectory();
142*33f37583SAndroid Build Coastguard Worker   }
GetTestFile(const std::string & name)143*33f37583SAndroid Build Coastguard Worker   static std::string GetTestFile(const std::string& name) {
144*33f37583SAndroid Build Coastguard Worker     return GetTestDataDir() + "/" + name;
145*33f37583SAndroid Build Coastguard Worker   }
146*33f37583SAndroid Build Coastguard Worker 
HaveSelinux()147*33f37583SAndroid Build Coastguard Worker   static bool HaveSelinux() { return 1 == is_selinux_enabled(); }
148*33f37583SAndroid Build Coastguard Worker 
IsSelinuxEnforced()149*33f37583SAndroid Build Coastguard Worker   static bool IsSelinuxEnforced() { return 0 != security_getenforce(); }
150*33f37583SAndroid Build Coastguard Worker 
GetAllPackages()151*33f37583SAndroid Build Coastguard Worker   Result<std::vector<ApexInfo>> GetAllPackages() {
152*33f37583SAndroid Build Coastguard Worker     std::vector<ApexInfo> list;
153*33f37583SAndroid Build Coastguard Worker     android::binder::Status status = service_->getAllPackages(&list);
154*33f37583SAndroid Build Coastguard Worker     if (status.isOk()) {
155*33f37583SAndroid Build Coastguard Worker       return list;
156*33f37583SAndroid Build Coastguard Worker     }
157*33f37583SAndroid Build Coastguard Worker 
158*33f37583SAndroid Build Coastguard Worker     return Error() << status.toString8().c_str();
159*33f37583SAndroid Build Coastguard Worker   }
160*33f37583SAndroid Build Coastguard Worker 
GetActivePackages()161*33f37583SAndroid Build Coastguard Worker   Result<std::vector<ApexInfo>> GetActivePackages() {
162*33f37583SAndroid Build Coastguard Worker     std::vector<ApexInfo> list;
163*33f37583SAndroid Build Coastguard Worker     android::binder::Status status = service_->getActivePackages(&list);
164*33f37583SAndroid Build Coastguard Worker     if (status.isOk()) {
165*33f37583SAndroid Build Coastguard Worker       return list;
166*33f37583SAndroid Build Coastguard Worker     }
167*33f37583SAndroid Build Coastguard Worker 
168*33f37583SAndroid Build Coastguard Worker     return Error() << status.exceptionMessage().c_str();
169*33f37583SAndroid Build Coastguard Worker   }
170*33f37583SAndroid Build Coastguard Worker 
GetInactivePackages()171*33f37583SAndroid Build Coastguard Worker   Result<std::vector<ApexInfo>> GetInactivePackages() {
172*33f37583SAndroid Build Coastguard Worker     std::vector<ApexInfo> list;
173*33f37583SAndroid Build Coastguard Worker     android::binder::Status status = service_->getAllPackages(&list);
174*33f37583SAndroid Build Coastguard Worker     list.erase(std::remove_if(
175*33f37583SAndroid Build Coastguard Worker                    list.begin(), list.end(),
176*33f37583SAndroid Build Coastguard Worker                    [](const ApexInfo& apexInfo) { return apexInfo.isActive; }),
177*33f37583SAndroid Build Coastguard Worker                list.end());
178*33f37583SAndroid Build Coastguard Worker     if (status.isOk()) {
179*33f37583SAndroid Build Coastguard Worker       return list;
180*33f37583SAndroid Build Coastguard Worker     }
181*33f37583SAndroid Build Coastguard Worker 
182*33f37583SAndroid Build Coastguard Worker     return Error() << status.toString8().c_str();
183*33f37583SAndroid Build Coastguard Worker   }
184*33f37583SAndroid Build Coastguard Worker 
GetPackageString(const ApexInfo & p)185*33f37583SAndroid Build Coastguard Worker   std::string GetPackageString(const ApexInfo& p) {
186*33f37583SAndroid Build Coastguard Worker     return p.moduleName + "@" + std::to_string(p.versionCode) +
187*33f37583SAndroid Build Coastguard Worker            " [path=" + p.moduleName + "]";
188*33f37583SAndroid Build Coastguard Worker   }
189*33f37583SAndroid Build Coastguard Worker 
GetPackagesStrings(const std::vector<ApexInfo> & list)190*33f37583SAndroid Build Coastguard Worker   std::vector<std::string> GetPackagesStrings(
191*33f37583SAndroid Build Coastguard Worker       const std::vector<ApexInfo>& list) {
192*33f37583SAndroid Build Coastguard Worker     std::vector<std::string> ret;
193*33f37583SAndroid Build Coastguard Worker     ret.reserve(list.size());
194*33f37583SAndroid Build Coastguard Worker     for (const ApexInfo& p : list) {
195*33f37583SAndroid Build Coastguard Worker       ret.push_back(GetPackageString(p));
196*33f37583SAndroid Build Coastguard Worker     }
197*33f37583SAndroid Build Coastguard Worker     return ret;
198*33f37583SAndroid Build Coastguard Worker   }
199*33f37583SAndroid Build Coastguard Worker 
GetActivePackagesStrings()200*33f37583SAndroid Build Coastguard Worker   std::vector<std::string> GetActivePackagesStrings() {
201*33f37583SAndroid Build Coastguard Worker     std::vector<ApexInfo> list;
202*33f37583SAndroid Build Coastguard Worker     android::binder::Status status = service_->getActivePackages(&list);
203*33f37583SAndroid Build Coastguard Worker     if (status.isOk()) {
204*33f37583SAndroid Build Coastguard Worker       std::vector<std::string> ret(list.size());
205*33f37583SAndroid Build Coastguard Worker       for (const ApexInfo& p : list) {
206*33f37583SAndroid Build Coastguard Worker         ret.push_back(GetPackageString(p));
207*33f37583SAndroid Build Coastguard Worker       }
208*33f37583SAndroid Build Coastguard Worker       return ret;
209*33f37583SAndroid Build Coastguard Worker     }
210*33f37583SAndroid Build Coastguard Worker 
211*33f37583SAndroid Build Coastguard Worker     std::vector<std::string> error;
212*33f37583SAndroid Build Coastguard Worker     error.push_back("ERROR");
213*33f37583SAndroid Build Coastguard Worker     return error;
214*33f37583SAndroid Build Coastguard Worker   }
215*33f37583SAndroid Build Coastguard Worker 
GetFactoryPackages()216*33f37583SAndroid Build Coastguard Worker   Result<std::vector<ApexInfo>> GetFactoryPackages() {
217*33f37583SAndroid Build Coastguard Worker     std::vector<ApexInfo> list;
218*33f37583SAndroid Build Coastguard Worker     android::binder::Status status = service_->getAllPackages(&list);
219*33f37583SAndroid Build Coastguard Worker     list.erase(
220*33f37583SAndroid Build Coastguard Worker         std::remove_if(list.begin(), list.end(),
221*33f37583SAndroid Build Coastguard Worker                        [](ApexInfo& apexInfo) { return !apexInfo.isFactory; }),
222*33f37583SAndroid Build Coastguard Worker         list.end());
223*33f37583SAndroid Build Coastguard Worker     if (status.isOk()) {
224*33f37583SAndroid Build Coastguard Worker       return list;
225*33f37583SAndroid Build Coastguard Worker     }
226*33f37583SAndroid Build Coastguard Worker 
227*33f37583SAndroid Build Coastguard Worker     return Error() << status.toString8().c_str();
228*33f37583SAndroid Build Coastguard Worker   }
229*33f37583SAndroid Build Coastguard Worker 
ListDir(const std::string & path)230*33f37583SAndroid Build Coastguard Worker   static std::vector<std::string> ListDir(const std::string& path) {
231*33f37583SAndroid Build Coastguard Worker     std::vector<std::string> ret;
232*33f37583SAndroid Build Coastguard Worker     std::error_code ec;
233*33f37583SAndroid Build Coastguard Worker     if (!fs::is_directory(path, ec)) {
234*33f37583SAndroid Build Coastguard Worker       return ret;
235*33f37583SAndroid Build Coastguard Worker     }
236*33f37583SAndroid Build Coastguard Worker     auto status = WalkDir(path, [&](const fs::directory_entry& entry) {
237*33f37583SAndroid Build Coastguard Worker       std::string tmp;
238*33f37583SAndroid Build Coastguard Worker       switch (entry.symlink_status(ec).type()) {
239*33f37583SAndroid Build Coastguard Worker         case fs::file_type::directory:
240*33f37583SAndroid Build Coastguard Worker           tmp = "[dir]";
241*33f37583SAndroid Build Coastguard Worker           break;
242*33f37583SAndroid Build Coastguard Worker         case fs::file_type::symlink:
243*33f37583SAndroid Build Coastguard Worker           tmp = "[lnk]";
244*33f37583SAndroid Build Coastguard Worker           break;
245*33f37583SAndroid Build Coastguard Worker         case fs::file_type::regular:
246*33f37583SAndroid Build Coastguard Worker           tmp = "[reg]";
247*33f37583SAndroid Build Coastguard Worker           break;
248*33f37583SAndroid Build Coastguard Worker         default:
249*33f37583SAndroid Build Coastguard Worker           tmp = "[other]";
250*33f37583SAndroid Build Coastguard Worker       }
251*33f37583SAndroid Build Coastguard Worker       ret.push_back(tmp.append(entry.path().filename()));
252*33f37583SAndroid Build Coastguard Worker     });
253*33f37583SAndroid Build Coastguard Worker     CHECK(status.has_value())
254*33f37583SAndroid Build Coastguard Worker         << "Failed to list " << path << " : " << status.error();
255*33f37583SAndroid Build Coastguard Worker     std::sort(ret.begin(), ret.end());
256*33f37583SAndroid Build Coastguard Worker     return ret;
257*33f37583SAndroid Build Coastguard Worker   }
258*33f37583SAndroid Build Coastguard Worker 
DeleteIfExists(const std::string & path)259*33f37583SAndroid Build Coastguard Worker   static void DeleteIfExists(const std::string& path) {
260*33f37583SAndroid Build Coastguard Worker     if (fs::exists(path)) {
261*33f37583SAndroid Build Coastguard Worker       std::error_code ec;
262*33f37583SAndroid Build Coastguard Worker       fs::remove_all(path, ec);
263*33f37583SAndroid Build Coastguard Worker       ASSERT_FALSE(ec) << "Failed to delete dir " << path << " : "
264*33f37583SAndroid Build Coastguard Worker                        << ec.message();
265*33f37583SAndroid Build Coastguard Worker     }
266*33f37583SAndroid Build Coastguard Worker   }
267*33f37583SAndroid Build Coastguard Worker 
268*33f37583SAndroid Build Coastguard Worker   struct PrepareTestApexForInstall {
269*33f37583SAndroid Build Coastguard Worker     static constexpr const char* kTestDir = "/data/app-staging/apexservice_tmp";
270*33f37583SAndroid Build Coastguard Worker 
271*33f37583SAndroid Build Coastguard Worker     // This is given to the constructor.
272*33f37583SAndroid Build Coastguard Worker     std::string test_input;           // Original test file.
273*33f37583SAndroid Build Coastguard Worker     std::string selinux_label_input;  // SELinux label to apply.
274*33f37583SAndroid Build Coastguard Worker     std::string test_dir_input;
275*33f37583SAndroid Build Coastguard Worker 
276*33f37583SAndroid Build Coastguard Worker     // This is derived from the input.
277*33f37583SAndroid Build Coastguard Worker     std::string test_file;            // Prepared path. Under test_dir_input.
278*33f37583SAndroid Build Coastguard Worker     std::string test_installed_file;  // Where apexd will store it.
279*33f37583SAndroid Build Coastguard Worker 
280*33f37583SAndroid Build Coastguard Worker     std::string package;  // APEX package name.
281*33f37583SAndroid Build Coastguard Worker     uint64_t version;     // APEX version
282*33f37583SAndroid Build Coastguard Worker 
PrepareTestApexForInstallandroid::apex::ApexServiceTest::PrepareTestApexForInstall283*33f37583SAndroid Build Coastguard Worker     explicit PrepareTestApexForInstall(
284*33f37583SAndroid Build Coastguard Worker         const std::string& test,
285*33f37583SAndroid Build Coastguard Worker         const std::string& test_dir = std::string(kTestDir),
286*33f37583SAndroid Build Coastguard Worker         const std::string& selinux_label = "staging_data_file") {
287*33f37583SAndroid Build Coastguard Worker       test_input = test;
288*33f37583SAndroid Build Coastguard Worker       selinux_label_input = selinux_label;
289*33f37583SAndroid Build Coastguard Worker       test_dir_input = test_dir;
290*33f37583SAndroid Build Coastguard Worker 
291*33f37583SAndroid Build Coastguard Worker       test_file = test_dir_input + "/" + android::base::Basename(test);
292*33f37583SAndroid Build Coastguard Worker 
293*33f37583SAndroid Build Coastguard Worker       package = "";  // Explicitly mark as not initialized.
294*33f37583SAndroid Build Coastguard Worker 
295*33f37583SAndroid Build Coastguard Worker       Result<ApexFile> apex_file = ApexFile::Open(test);
296*33f37583SAndroid Build Coastguard Worker       if (!apex_file.ok()) {
297*33f37583SAndroid Build Coastguard Worker         return;
298*33f37583SAndroid Build Coastguard Worker       }
299*33f37583SAndroid Build Coastguard Worker 
300*33f37583SAndroid Build Coastguard Worker       const ApexManifest& manifest = apex_file->GetManifest();
301*33f37583SAndroid Build Coastguard Worker       package = manifest.name();
302*33f37583SAndroid Build Coastguard Worker       version = manifest.version();
303*33f37583SAndroid Build Coastguard Worker 
304*33f37583SAndroid Build Coastguard Worker       test_installed_file = std::string(kActiveApexPackagesDataDir) + "/" +
305*33f37583SAndroid Build Coastguard Worker                             package + "@" + std::to_string(version) + ".apex";
306*33f37583SAndroid Build Coastguard Worker     }
307*33f37583SAndroid Build Coastguard Worker 
Prepareandroid::apex::ApexServiceTest::PrepareTestApexForInstall308*33f37583SAndroid Build Coastguard Worker     bool Prepare() {
309*33f37583SAndroid Build Coastguard Worker       if (package.empty()) {
310*33f37583SAndroid Build Coastguard Worker         // Failure in constructor. Redo work to get error message.
311*33f37583SAndroid Build Coastguard Worker         auto fail_fn = [&]() {
312*33f37583SAndroid Build Coastguard Worker           Result<ApexFile> apex_file = ApexFile::Open(test_input);
313*33f37583SAndroid Build Coastguard Worker           ASSERT_THAT(apex_file, Not(Ok()));
314*33f37583SAndroid Build Coastguard Worker           ASSERT_TRUE(apex_file.ok())
315*33f37583SAndroid Build Coastguard Worker               << test_input << " failed to load: " << apex_file.error();
316*33f37583SAndroid Build Coastguard Worker         };
317*33f37583SAndroid Build Coastguard Worker         fail_fn();
318*33f37583SAndroid Build Coastguard Worker         return false;
319*33f37583SAndroid Build Coastguard Worker       }
320*33f37583SAndroid Build Coastguard Worker 
321*33f37583SAndroid Build Coastguard Worker       auto prepare = [](const std::string& src, const std::string& trg,
322*33f37583SAndroid Build Coastguard Worker                         const std::string& selinux_label) {
323*33f37583SAndroid Build Coastguard Worker         ASSERT_EQ(0, access(src.c_str(), F_OK))
324*33f37583SAndroid Build Coastguard Worker             << src << ": " << strerror(errno);
325*33f37583SAndroid Build Coastguard Worker         const std::string trg_dir = android::base::Dirname(trg);
326*33f37583SAndroid Build Coastguard Worker         if (0 != mkdir(trg_dir.c_str(), 0777)) {
327*33f37583SAndroid Build Coastguard Worker           int saved_errno = errno;
328*33f37583SAndroid Build Coastguard Worker           ASSERT_EQ(saved_errno, EEXIST) << trg << ":" << strerror(saved_errno);
329*33f37583SAndroid Build Coastguard Worker         }
330*33f37583SAndroid Build Coastguard Worker 
331*33f37583SAndroid Build Coastguard Worker         // Do not use a hardlink, even though it's the simplest solution.
332*33f37583SAndroid Build Coastguard Worker         // b/119569101.
333*33f37583SAndroid Build Coastguard Worker         {
334*33f37583SAndroid Build Coastguard Worker           std::ifstream src_stream(src, std::ios::binary);
335*33f37583SAndroid Build Coastguard Worker           ASSERT_TRUE(src_stream.good());
336*33f37583SAndroid Build Coastguard Worker           std::ofstream trg_stream(trg, std::ios::binary);
337*33f37583SAndroid Build Coastguard Worker           ASSERT_TRUE(trg_stream.good());
338*33f37583SAndroid Build Coastguard Worker 
339*33f37583SAndroid Build Coastguard Worker           trg_stream << src_stream.rdbuf();
340*33f37583SAndroid Build Coastguard Worker         }
341*33f37583SAndroid Build Coastguard Worker 
342*33f37583SAndroid Build Coastguard Worker         ASSERT_EQ(0, chmod(trg.c_str(), 0666)) << strerror(errno);
343*33f37583SAndroid Build Coastguard Worker         struct group* g = getgrnam("system");
344*33f37583SAndroid Build Coastguard Worker         ASSERT_NE(nullptr, g);
345*33f37583SAndroid Build Coastguard Worker         ASSERT_EQ(0, chown(trg.c_str(), /* root uid */ 0, g->gr_gid))
346*33f37583SAndroid Build Coastguard Worker             << strerror(errno);
347*33f37583SAndroid Build Coastguard Worker 
348*33f37583SAndroid Build Coastguard Worker         int rc = setfilecon(
349*33f37583SAndroid Build Coastguard Worker             trg_dir.c_str(),
350*33f37583SAndroid Build Coastguard Worker             std::string("u:object_r:" + selinux_label + ":s0").c_str());
351*33f37583SAndroid Build Coastguard Worker         ASSERT_TRUE(0 == rc || !HaveSelinux()) << strerror(errno);
352*33f37583SAndroid Build Coastguard Worker         rc = setfilecon(
353*33f37583SAndroid Build Coastguard Worker             trg.c_str(),
354*33f37583SAndroid Build Coastguard Worker             std::string("u:object_r:" + selinux_label + ":s0").c_str());
355*33f37583SAndroid Build Coastguard Worker         ASSERT_TRUE(0 == rc || !HaveSelinux()) << strerror(errno);
356*33f37583SAndroid Build Coastguard Worker       };
357*33f37583SAndroid Build Coastguard Worker       prepare(test_input, test_file, selinux_label_input);
358*33f37583SAndroid Build Coastguard Worker       return !HasFatalFailure();
359*33f37583SAndroid Build Coastguard Worker     }
360*33f37583SAndroid Build Coastguard Worker 
~PrepareTestApexForInstallandroid::apex::ApexServiceTest::PrepareTestApexForInstall361*33f37583SAndroid Build Coastguard Worker     ~PrepareTestApexForInstall() {
362*33f37583SAndroid Build Coastguard Worker       LOG(INFO) << "Deleting file " << test_file;
363*33f37583SAndroid Build Coastguard Worker       if (unlink(test_file.c_str()) != 0) {
364*33f37583SAndroid Build Coastguard Worker         PLOG(ERROR) << "Unable to unlink " << test_file;
365*33f37583SAndroid Build Coastguard Worker       }
366*33f37583SAndroid Build Coastguard Worker       LOG(INFO) << "Deleting directory " << test_dir_input;
367*33f37583SAndroid Build Coastguard Worker       if (rmdir(test_dir_input.c_str()) != 0) {
368*33f37583SAndroid Build Coastguard Worker         PLOG(ERROR) << "Unable to rmdir " << test_dir_input;
369*33f37583SAndroid Build Coastguard Worker       }
370*33f37583SAndroid Build Coastguard Worker     }
371*33f37583SAndroid Build Coastguard Worker   };
372*33f37583SAndroid Build Coastguard Worker 
GetDebugStr(PrepareTestApexForInstall * installer)373*33f37583SAndroid Build Coastguard Worker   std::string GetDebugStr(PrepareTestApexForInstall* installer) {
374*33f37583SAndroid Build Coastguard Worker     StringLog log;
375*33f37583SAndroid Build Coastguard Worker 
376*33f37583SAndroid Build Coastguard Worker     if (installer != nullptr) {
377*33f37583SAndroid Build Coastguard Worker       log << "test_input=" << installer->test_input << " ";
378*33f37583SAndroid Build Coastguard Worker       log << "test_file=" << installer->test_file << " ";
379*33f37583SAndroid Build Coastguard Worker       log << "test_installed_file=" << installer->test_installed_file << " ";
380*33f37583SAndroid Build Coastguard Worker       log << "package=" << installer->package << " ";
381*33f37583SAndroid Build Coastguard Worker       log << "version=" << installer->version << " ";
382*33f37583SAndroid Build Coastguard Worker     }
383*33f37583SAndroid Build Coastguard Worker 
384*33f37583SAndroid Build Coastguard Worker     log << "active=[" << Join(GetActivePackagesStrings(), ',') << "] ";
385*33f37583SAndroid Build Coastguard Worker     log << kActiveApexPackagesDataDir << "=["
386*33f37583SAndroid Build Coastguard Worker         << Join(ListDir(kActiveApexPackagesDataDir), ',') << "] ";
387*33f37583SAndroid Build Coastguard Worker     log << kApexRoot << "=[" << Join(ListDir(kApexRoot), ',') << "]";
388*33f37583SAndroid Build Coastguard Worker 
389*33f37583SAndroid Build Coastguard Worker     return log;
390*33f37583SAndroid Build Coastguard Worker   }
391*33f37583SAndroid Build Coastguard Worker 
392*33f37583SAndroid Build Coastguard Worker   sp<IApexService> service_;
393*33f37583SAndroid Build Coastguard Worker   sp<android::os::IVold> vold_service_;
394*33f37583SAndroid Build Coastguard Worker   bool supports_fs_checkpointing_;
395*33f37583SAndroid Build Coastguard Worker   std::unique_ptr<ApexSessionManager> session_manager_;
396*33f37583SAndroid Build Coastguard Worker 
397*33f37583SAndroid Build Coastguard Worker  private:
CleanUp()398*33f37583SAndroid Build Coastguard Worker   void CleanUp() {
399*33f37583SAndroid Build Coastguard Worker     DeleteDirContent(kActiveApexPackagesDataDir);
400*33f37583SAndroid Build Coastguard Worker     DeleteDirContent(kApexBackupDir);
401*33f37583SAndroid Build Coastguard Worker     DeleteDirContent(GetSessionsDir());
402*33f37583SAndroid Build Coastguard Worker 
403*33f37583SAndroid Build Coastguard Worker     DeleteIfExists("/data/misc_ce/0/apexdata/apex.apexd_test");
404*33f37583SAndroid Build Coastguard Worker     DeleteIfExists("/data/misc_ce/0/apexrollback/123456");
405*33f37583SAndroid Build Coastguard Worker     DeleteIfExists("/data/misc_ce/0/apexrollback/77777");
406*33f37583SAndroid Build Coastguard Worker     DeleteIfExists("/data/misc_ce/0/apexrollback/98765");
407*33f37583SAndroid Build Coastguard Worker     DeleteIfExists("/data/misc_de/0/apexrollback/123456");
408*33f37583SAndroid Build Coastguard Worker     DeleteIfExists("/data/misc/apexrollback/123456");
409*33f37583SAndroid Build Coastguard Worker   }
410*33f37583SAndroid Build Coastguard Worker };
411*33f37583SAndroid Build Coastguard Worker 
412*33f37583SAndroid Build Coastguard Worker namespace {
413*33f37583SAndroid Build Coastguard Worker 
RegularFileExists(const std::string & path)414*33f37583SAndroid Build Coastguard Worker bool RegularFileExists(const std::string& path) {
415*33f37583SAndroid Build Coastguard Worker   struct stat buf;
416*33f37583SAndroid Build Coastguard Worker   if (0 != stat(path.c_str(), &buf)) {
417*33f37583SAndroid Build Coastguard Worker     return false;
418*33f37583SAndroid Build Coastguard Worker   }
419*33f37583SAndroid Build Coastguard Worker   return S_ISREG(buf.st_mode);
420*33f37583SAndroid Build Coastguard Worker }
421*33f37583SAndroid Build Coastguard Worker 
DirExists(const std::string & path)422*33f37583SAndroid Build Coastguard Worker bool DirExists(const std::string& path) {
423*33f37583SAndroid Build Coastguard Worker   struct stat buf;
424*33f37583SAndroid Build Coastguard Worker   if (0 != stat(path.c_str(), &buf)) {
425*33f37583SAndroid Build Coastguard Worker     return false;
426*33f37583SAndroid Build Coastguard Worker   }
427*33f37583SAndroid Build Coastguard Worker   return S_ISDIR(buf.st_mode);
428*33f37583SAndroid Build Coastguard Worker }
429*33f37583SAndroid Build Coastguard Worker 
CreateDir(const std::string & path)430*33f37583SAndroid Build Coastguard Worker void CreateDir(const std::string& path) {
431*33f37583SAndroid Build Coastguard Worker   std::error_code ec;
432*33f37583SAndroid Build Coastguard Worker   fs::create_directory(path, ec);
433*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(ec) << "Failed to create rollback dir "
434*33f37583SAndroid Build Coastguard Worker                    << " : " << ec.message();
435*33f37583SAndroid Build Coastguard Worker }
436*33f37583SAndroid Build Coastguard Worker 
CreateFile(const std::string & path)437*33f37583SAndroid Build Coastguard Worker void CreateFile(const std::string& path) {
438*33f37583SAndroid Build Coastguard Worker   std::ofstream ofs(path);
439*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(ofs.good());
440*33f37583SAndroid Build Coastguard Worker   ofs.close();
441*33f37583SAndroid Build Coastguard Worker }
442*33f37583SAndroid Build Coastguard Worker 
CreateFileWithExpectedProperties(const std::string & path)443*33f37583SAndroid Build Coastguard Worker void CreateFileWithExpectedProperties(const std::string& path) {
444*33f37583SAndroid Build Coastguard Worker   CreateFile(path);
445*33f37583SAndroid Build Coastguard Worker   std::error_code ec;
446*33f37583SAndroid Build Coastguard Worker   fs::permissions(
447*33f37583SAndroid Build Coastguard Worker       path,
448*33f37583SAndroid Build Coastguard Worker       fs::perms::owner_read | fs::perms::group_write | fs::perms::others_exec,
449*33f37583SAndroid Build Coastguard Worker       fs::perm_options::replace, ec);
450*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(ec) << "Failed to set permissions: " << ec.message();
451*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(0, chown(path.c_str(), 1007 /* log */, 3001 /* net_bt_admin */))
452*33f37583SAndroid Build Coastguard Worker       << "chown failed: " << strerror(errno);
453*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(RegularFileExists(path));
454*33f37583SAndroid Build Coastguard Worker   char buf[65536];  // 64kB is max possible xattr list size. See "man 7 xattr".
455*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(0, setxattr(path.c_str(), "user.foo", "bar", 4, 0));
456*33f37583SAndroid Build Coastguard Worker   ASSERT_GE(listxattr(path.c_str(), buf, sizeof(buf)), 9);
457*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(memmem(buf, sizeof(buf), "user.foo", 9) != nullptr);
458*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(4, getxattr(path.c_str(), "user.foo", buf, sizeof(buf)));
459*33f37583SAndroid Build Coastguard Worker   ASSERT_STREQ("bar", buf);
460*33f37583SAndroid Build Coastguard Worker }
461*33f37583SAndroid Build Coastguard Worker 
ExpectFileWithExpectedProperties(const std::string & path)462*33f37583SAndroid Build Coastguard Worker void ExpectFileWithExpectedProperties(const std::string& path) {
463*33f37583SAndroid Build Coastguard Worker   EXPECT_TRUE(RegularFileExists(path));
464*33f37583SAndroid Build Coastguard Worker   EXPECT_EQ(fs::status(path).permissions(), fs::perms::owner_read |
465*33f37583SAndroid Build Coastguard Worker                                                 fs::perms::group_write |
466*33f37583SAndroid Build Coastguard Worker                                                 fs::perms::others_exec);
467*33f37583SAndroid Build Coastguard Worker   struct stat sd;
468*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(0, stat(path.c_str(), &sd));
469*33f37583SAndroid Build Coastguard Worker   EXPECT_EQ(1007u, sd.st_uid);
470*33f37583SAndroid Build Coastguard Worker   EXPECT_EQ(3001u, sd.st_gid);
471*33f37583SAndroid Build Coastguard Worker   char buf[65536];  // 64kB is max possible xattr list size. See "man 7 xattr".
472*33f37583SAndroid Build Coastguard Worker   EXPECT_GE(listxattr(path.c_str(), buf, sizeof(buf)), 9);
473*33f37583SAndroid Build Coastguard Worker   EXPECT_TRUE(memmem(buf, sizeof(buf), "user.foo", 9) != nullptr);
474*33f37583SAndroid Build Coastguard Worker   EXPECT_EQ(4, getxattr(path.c_str(), "user.foo", buf, sizeof(buf)));
475*33f37583SAndroid Build Coastguard Worker   EXPECT_STREQ("bar", buf);
476*33f37583SAndroid Build Coastguard Worker }
477*33f37583SAndroid Build Coastguard Worker 
ReadEntireDir(const std::string & path)478*33f37583SAndroid Build Coastguard Worker Result<std::vector<std::string>> ReadEntireDir(const std::string& path) {
479*33f37583SAndroid Build Coastguard Worker   static const auto kAcceptAll = [](auto /*entry*/) { return true; };
480*33f37583SAndroid Build Coastguard Worker   return ReadDir(path, kAcceptAll);
481*33f37583SAndroid Build Coastguard Worker }
482*33f37583SAndroid Build Coastguard Worker 
483*33f37583SAndroid Build Coastguard Worker }  // namespace
484*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,HaveSelinux)485*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, HaveSelinux) {
486*33f37583SAndroid Build Coastguard Worker   // We want to test under selinux.
487*33f37583SAndroid Build Coastguard Worker   EXPECT_TRUE(HaveSelinux());
488*33f37583SAndroid Build Coastguard Worker }
489*33f37583SAndroid Build Coastguard Worker 
490*33f37583SAndroid Build Coastguard Worker // Skip for b/119032200.
TEST_F(ApexServiceTest,DISABLED_EnforceSelinux)491*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, DISABLED_EnforceSelinux) {
492*33f37583SAndroid Build Coastguard Worker   // Crude cutout for virtual devices.
493*33f37583SAndroid Build Coastguard Worker #if !defined(__i386__) && !defined(__x86_64__)
494*33f37583SAndroid Build Coastguard Worker   constexpr bool kIsX86 = false;
495*33f37583SAndroid Build Coastguard Worker #else
496*33f37583SAndroid Build Coastguard Worker   constexpr bool kIsX86 = true;
497*33f37583SAndroid Build Coastguard Worker #endif
498*33f37583SAndroid Build Coastguard Worker   EXPECT_TRUE(IsSelinuxEnforced() || kIsX86);
499*33f37583SAndroid Build Coastguard Worker }
500*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,SubmitStagegSessionSuccessDoesNotLeakTempVerityDevices)501*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest,
502*33f37583SAndroid Build Coastguard Worker        SubmitStagegSessionSuccessDoesNotLeakTempVerityDevices) {
503*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
504*33f37583SAndroid Build Coastguard Worker                                       "/data/app-staging/session_1543",
505*33f37583SAndroid Build Coastguard Worker                                       "staging_data_file");
506*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
507*33f37583SAndroid Build Coastguard Worker     return;
508*33f37583SAndroid Build Coastguard Worker   }
509*33f37583SAndroid Build Coastguard Worker 
510*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
511*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
512*33f37583SAndroid Build Coastguard Worker   params.sessionId = 1543;
513*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->submitStagedSession(params, &list)));
514*33f37583SAndroid Build Coastguard Worker 
515*33f37583SAndroid Build Coastguard Worker   std::vector<DeviceMapper::DmBlockDevice> devices;
516*33f37583SAndroid Build Coastguard Worker   DeviceMapper& dm = DeviceMapper::Instance();
517*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(dm.GetAvailableDevices(&devices));
518*33f37583SAndroid Build Coastguard Worker 
519*33f37583SAndroid Build Coastguard Worker   for (const auto& device : devices) {
520*33f37583SAndroid Build Coastguard Worker     ASSERT_THAT(device.name(), Not(EndsWith(".tmp")));
521*33f37583SAndroid Build Coastguard Worker   }
522*33f37583SAndroid Build Coastguard Worker }
523*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,SubmitStagedSessionStoresBuildFingerprint)524*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, SubmitStagedSessionStoresBuildFingerprint) {
525*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
526*33f37583SAndroid Build Coastguard Worker                                       "/data/app-staging/session_1547",
527*33f37583SAndroid Build Coastguard Worker                                       "staging_data_file");
528*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
529*33f37583SAndroid Build Coastguard Worker     return;
530*33f37583SAndroid Build Coastguard Worker   }
531*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
532*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
533*33f37583SAndroid Build Coastguard Worker   params.sessionId = 1547;
534*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->submitStagedSession(params, &list)));
535*33f37583SAndroid Build Coastguard Worker 
536*33f37583SAndroid Build Coastguard Worker   auto session = GetSession(1547);
537*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(session->GetBuildFingerprint().empty());
538*33f37583SAndroid Build Coastguard Worker }
539*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,SubmitStagedSessionFailDoesNotLeakTempVerityDevices)540*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, SubmitStagedSessionFailDoesNotLeakTempVerityDevices) {
541*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(
542*33f37583SAndroid Build Coastguard Worker       GetTestFile("apex.apexd_test_manifest_mismatch.apex"),
543*33f37583SAndroid Build Coastguard Worker       "/data/app-staging/session_239", "staging_data_file");
544*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
545*33f37583SAndroid Build Coastguard Worker     return;
546*33f37583SAndroid Build Coastguard Worker   }
547*33f37583SAndroid Build Coastguard Worker 
548*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
549*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
550*33f37583SAndroid Build Coastguard Worker   params.sessionId = 239;
551*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->submitStagedSession(params, &list)));
552*33f37583SAndroid Build Coastguard Worker 
553*33f37583SAndroid Build Coastguard Worker   std::vector<DeviceMapper::DmBlockDevice> devices;
554*33f37583SAndroid Build Coastguard Worker   DeviceMapper& dm = DeviceMapper::Instance();
555*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(dm.GetAvailableDevices(&devices));
556*33f37583SAndroid Build Coastguard Worker 
557*33f37583SAndroid Build Coastguard Worker   for (const auto& device : devices) {
558*33f37583SAndroid Build Coastguard Worker     ASSERT_THAT(device.name(), Not(EndsWith(".tmp")));
559*33f37583SAndroid Build Coastguard Worker   }
560*33f37583SAndroid Build Coastguard Worker }
561*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,CannotBeRollbackAndHaveRollbackEnabled)562*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, CannotBeRollbackAndHaveRollbackEnabled) {
563*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
564*33f37583SAndroid Build Coastguard Worker                                       "/data/app-staging/session_1543",
565*33f37583SAndroid Build Coastguard Worker                                       "staging_data_file");
566*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
567*33f37583SAndroid Build Coastguard Worker     return;
568*33f37583SAndroid Build Coastguard Worker   }
569*33f37583SAndroid Build Coastguard Worker 
570*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
571*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
572*33f37583SAndroid Build Coastguard Worker   params.sessionId = 1543;
573*33f37583SAndroid Build Coastguard Worker   params.isRollback = true;
574*33f37583SAndroid Build Coastguard Worker   params.hasRollbackEnabled = true;
575*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->submitStagedSession(params, &list)));
576*33f37583SAndroid Build Coastguard Worker }
577*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,SessionParamDefaults)578*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, SessionParamDefaults) {
579*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
580*33f37583SAndroid Build Coastguard Worker                                       "/data/app-staging/session_1547",
581*33f37583SAndroid Build Coastguard Worker                                       "staging_data_file");
582*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
583*33f37583SAndroid Build Coastguard Worker     return;
584*33f37583SAndroid Build Coastguard Worker   }
585*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
586*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
587*33f37583SAndroid Build Coastguard Worker   params.sessionId = 1547;
588*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->submitStagedSession(params, &list)));
589*33f37583SAndroid Build Coastguard Worker 
590*33f37583SAndroid Build Coastguard Worker   auto session = GetSession(1547);
591*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(session->GetChildSessionIds().empty());
592*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(session->IsRollback());
593*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(session->HasRollbackEnabled());
594*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(0, session->GetRollbackId());
595*33f37583SAndroid Build Coastguard Worker }
596*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,SnapshotCeData)597*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, SnapshotCeData) {
598*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_ce/0/apexdata/apex.apexd_test");
599*33f37583SAndroid Build Coastguard Worker   CreateFileWithExpectedProperties(
600*33f37583SAndroid Build Coastguard Worker       "/data/misc_ce/0/apexdata/apex.apexd_test/hello.txt");
601*33f37583SAndroid Build Coastguard Worker 
602*33f37583SAndroid Build Coastguard Worker   service_->snapshotCeData(0, 123456, "apex.apexd_test");
603*33f37583SAndroid Build Coastguard Worker 
604*33f37583SAndroid Build Coastguard Worker   ExpectFileWithExpectedProperties(
605*33f37583SAndroid Build Coastguard Worker       "/data/misc_ce/0/apexrollback/123456/apex.apexd_test/hello.txt");
606*33f37583SAndroid Build Coastguard Worker }
607*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,RestoreCeData)608*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, RestoreCeData) {
609*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_ce/0/apexdata/apex.apexd_test");
610*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_ce/0/apexrollback/123456");
611*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_ce/0/apexrollback/123456/apex.apexd_test");
612*33f37583SAndroid Build Coastguard Worker 
613*33f37583SAndroid Build Coastguard Worker   CreateFile("/data/misc_ce/0/apexdata/apex.apexd_test/newfile.txt");
614*33f37583SAndroid Build Coastguard Worker   CreateFileWithExpectedProperties(
615*33f37583SAndroid Build Coastguard Worker       "/data/misc_ce/0/apexrollback/123456/apex.apexd_test/oldfile.txt");
616*33f37583SAndroid Build Coastguard Worker 
617*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(RegularFileExists(
618*33f37583SAndroid Build Coastguard Worker       "/data/misc_ce/0/apexdata/apex.apexd_test/newfile.txt"));
619*33f37583SAndroid Build Coastguard Worker   ExpectFileWithExpectedProperties(
620*33f37583SAndroid Build Coastguard Worker       "/data/misc_ce/0/apexrollback/123456/apex.apexd_test/oldfile.txt");
621*33f37583SAndroid Build Coastguard Worker 
622*33f37583SAndroid Build Coastguard Worker   service_->restoreCeData(0, 123456, "apex.apexd_test");
623*33f37583SAndroid Build Coastguard Worker 
624*33f37583SAndroid Build Coastguard Worker   ExpectFileWithExpectedProperties(
625*33f37583SAndroid Build Coastguard Worker       "/data/misc_ce/0/apexdata/apex.apexd_test/oldfile.txt");
626*33f37583SAndroid Build Coastguard Worker   EXPECT_FALSE(RegularFileExists(
627*33f37583SAndroid Build Coastguard Worker       "/data/misc_ce/0/apexdata/apex.apexd_test/newfile.txt"));
628*33f37583SAndroid Build Coastguard Worker   // The snapshot should be deleted after restoration.
629*33f37583SAndroid Build Coastguard Worker   EXPECT_FALSE(
630*33f37583SAndroid Build Coastguard Worker       DirExists("/data/misc_ce/0/apexrollback/123456/apex.apexd_test"));
631*33f37583SAndroid Build Coastguard Worker }
632*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,DestroyDeSnapshotsDeSys)633*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, DestroyDeSnapshotsDeSys) {
634*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc/apexrollback/123456");
635*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc/apexrollback/123456/my.apex");
636*33f37583SAndroid Build Coastguard Worker   CreateFile("/data/misc/apexrollback/123456/my.apex/hello.txt");
637*33f37583SAndroid Build Coastguard Worker 
638*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(
639*33f37583SAndroid Build Coastguard Worker       RegularFileExists("/data/misc/apexrollback/123456/my.apex/hello.txt"));
640*33f37583SAndroid Build Coastguard Worker 
641*33f37583SAndroid Build Coastguard Worker   service_->destroyDeSnapshots(8975);
642*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(
643*33f37583SAndroid Build Coastguard Worker       RegularFileExists("/data/misc/apexrollback/123456/my.apex/hello.txt"));
644*33f37583SAndroid Build Coastguard Worker 
645*33f37583SAndroid Build Coastguard Worker   service_->destroyDeSnapshots(123456);
646*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(
647*33f37583SAndroid Build Coastguard Worker       RegularFileExists("/data/misc/apexrollback/123456/my.apex/hello.txt"));
648*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(DirExists("/data/misc/apexrollback/123456"));
649*33f37583SAndroid Build Coastguard Worker }
650*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,DestroyDeSnapshotsDeUser)651*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, DestroyDeSnapshotsDeUser) {
652*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_de/0/apexrollback/123456");
653*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_de/0/apexrollback/123456/my.apex");
654*33f37583SAndroid Build Coastguard Worker   CreateFile("/data/misc_de/0/apexrollback/123456/my.apex/hello.txt");
655*33f37583SAndroid Build Coastguard Worker 
656*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(RegularFileExists(
657*33f37583SAndroid Build Coastguard Worker       "/data/misc_de/0/apexrollback/123456/my.apex/hello.txt"));
658*33f37583SAndroid Build Coastguard Worker 
659*33f37583SAndroid Build Coastguard Worker   service_->destroyDeSnapshots(8975);
660*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(RegularFileExists(
661*33f37583SAndroid Build Coastguard Worker       "/data/misc_de/0/apexrollback/123456/my.apex/hello.txt"));
662*33f37583SAndroid Build Coastguard Worker 
663*33f37583SAndroid Build Coastguard Worker   service_->destroyDeSnapshots(123456);
664*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(RegularFileExists(
665*33f37583SAndroid Build Coastguard Worker       "/data/misc_de/0/apexrollback/123456/my.apex/hello.txt"));
666*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(DirExists("/data/misc_de/0/apexrollback/123456"));
667*33f37583SAndroid Build Coastguard Worker }
668*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,DestroyCeSnapshots)669*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, DestroyCeSnapshots) {
670*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_ce/0/apexrollback/123456");
671*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_ce/0/apexrollback/123456/apex.apexd_test");
672*33f37583SAndroid Build Coastguard Worker   CreateFile("/data/misc_ce/0/apexrollback/123456/apex.apexd_test/file.txt");
673*33f37583SAndroid Build Coastguard Worker 
674*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_ce/0/apexrollback/77777");
675*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_ce/0/apexrollback/77777/apex.apexd_test");
676*33f37583SAndroid Build Coastguard Worker   CreateFile("/data/misc_ce/0/apexrollback/77777/apex.apexd_test/thing.txt");
677*33f37583SAndroid Build Coastguard Worker 
678*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(RegularFileExists(
679*33f37583SAndroid Build Coastguard Worker       "/data/misc_ce/0/apexrollback/123456/apex.apexd_test/file.txt"));
680*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(RegularFileExists(
681*33f37583SAndroid Build Coastguard Worker       "/data/misc_ce/0/apexrollback/77777/apex.apexd_test/thing.txt"));
682*33f37583SAndroid Build Coastguard Worker 
683*33f37583SAndroid Build Coastguard Worker   android::binder::Status st = service_->destroyCeSnapshots(0, 123456);
684*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(st));
685*33f37583SAndroid Build Coastguard Worker   // Should be OK if the directory doesn't exist.
686*33f37583SAndroid Build Coastguard Worker   st = service_->destroyCeSnapshots(1, 123456);
687*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(st));
688*33f37583SAndroid Build Coastguard Worker 
689*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(RegularFileExists(
690*33f37583SAndroid Build Coastguard Worker       "/data/misc_ce/0/apexrollback/77777/apex.apexd_test/thing.txt"));
691*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(DirExists("/data/misc_ce/0/apexrollback/123456"));
692*33f37583SAndroid Build Coastguard Worker }
693*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,DestroyCeSnapshotsNotSpecified)694*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, DestroyCeSnapshotsNotSpecified) {
695*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_ce/0/apexrollback/123456");
696*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_ce/0/apexrollback/123456/apex.apexd_test");
697*33f37583SAndroid Build Coastguard Worker   CreateFile("/data/misc_ce/0/apexrollback/123456/apex.apexd_test/file.txt");
698*33f37583SAndroid Build Coastguard Worker 
699*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_ce/0/apexrollback/77777");
700*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_ce/0/apexrollback/77777/apex.apexd_test");
701*33f37583SAndroid Build Coastguard Worker   CreateFile("/data/misc_ce/0/apexrollback/77777/apex.apexd_test/thing.txt");
702*33f37583SAndroid Build Coastguard Worker 
703*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_ce/0/apexrollback/98765");
704*33f37583SAndroid Build Coastguard Worker   CreateDir("/data/misc_ce/0/apexrollback/98765/apex.apexd_test");
705*33f37583SAndroid Build Coastguard Worker   CreateFile("/data/misc_ce/0/apexrollback/98765/apex.apexd_test/test.txt");
706*33f37583SAndroid Build Coastguard Worker 
707*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(RegularFileExists(
708*33f37583SAndroid Build Coastguard Worker       "/data/misc_ce/0/apexrollback/123456/apex.apexd_test/file.txt"));
709*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(RegularFileExists(
710*33f37583SAndroid Build Coastguard Worker       "/data/misc_ce/0/apexrollback/77777/apex.apexd_test/thing.txt"));
711*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(RegularFileExists(
712*33f37583SAndroid Build Coastguard Worker       "/data/misc_ce/0/apexrollback/98765/apex.apexd_test/test.txt"));
713*33f37583SAndroid Build Coastguard Worker 
714*33f37583SAndroid Build Coastguard Worker   std::vector<int> retain{123, 77777, 987654};
715*33f37583SAndroid Build Coastguard Worker   android::binder::Status st =
716*33f37583SAndroid Build Coastguard Worker       service_->destroyCeSnapshotsNotSpecified(0, retain);
717*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(st));
718*33f37583SAndroid Build Coastguard Worker 
719*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(RegularFileExists(
720*33f37583SAndroid Build Coastguard Worker       "/data/misc_ce/0/apexrollback/77777/apex.apexd_test/thing.txt"));
721*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(DirExists("/data/misc_ce/0/apexrollback/123456"));
722*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(DirExists("/data/misc_ce/0/apexrollback/98765"));
723*33f37583SAndroid Build Coastguard Worker }
724*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,SubmitStagedSessionCleanupsTempMountOnFailure)725*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, SubmitStagedSessionCleanupsTempMountOnFailure) {
726*33f37583SAndroid Build Coastguard Worker   // Parent session id: 23
727*33f37583SAndroid Build Coastguard Worker   // Children session ids: 37 73
728*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(
729*33f37583SAndroid Build Coastguard Worker       GetTestFile("apex.apexd_test_different_app.apex"),
730*33f37583SAndroid Build Coastguard Worker       "/data/app-staging/session_37", "staging_data_file");
731*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer2(
732*33f37583SAndroid Build Coastguard Worker       GetTestFile("apex.apexd_test_manifest_mismatch.apex"),
733*33f37583SAndroid Build Coastguard Worker       "/data/app-staging/session_73", "staging_data_file");
734*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare() || !installer2.Prepare()) {
735*33f37583SAndroid Build Coastguard Worker     FAIL() << GetDebugStr(&installer) << GetDebugStr(&installer2);
736*33f37583SAndroid Build Coastguard Worker   }
737*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
738*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
739*33f37583SAndroid Build Coastguard Worker   params.sessionId = 23;
740*33f37583SAndroid Build Coastguard Worker   params.childSessionIds = {37, 73};
741*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->submitStagedSession(params, &list)))
742*33f37583SAndroid Build Coastguard Worker       << GetDebugStr(&installer);
743*33f37583SAndroid Build Coastguard Worker 
744*33f37583SAndroid Build Coastguard Worker   // Check that temp mounts were cleanded up.
745*33f37583SAndroid Build Coastguard Worker   for (const auto& mount : GetApexMounts()) {
746*33f37583SAndroid Build Coastguard Worker     EXPECT_FALSE(EndsWith(mount, ".tmp")) << "Found temp mount " << mount;
747*33f37583SAndroid Build Coastguard Worker   }
748*33f37583SAndroid Build Coastguard Worker }
749*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,GetFactoryPackages)750*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, GetFactoryPackages) {
751*33f37583SAndroid Build Coastguard Worker   Result<std::vector<ApexInfo>> factory_packages = GetFactoryPackages();
752*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(factory_packages);
753*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(factory_packages->size() > 0);
754*33f37583SAndroid Build Coastguard Worker 
755*33f37583SAndroid Build Coastguard Worker   std::vector<std::string> builtin_dirs;
756*33f37583SAndroid Build Coastguard Worker   for (const auto& d : kApexPackageBuiltinDirs) {
757*33f37583SAndroid Build Coastguard Worker     std::string realpath;
758*33f37583SAndroid Build Coastguard Worker     if (android::base::Realpath(d, &realpath)) {
759*33f37583SAndroid Build Coastguard Worker       builtin_dirs.push_back(realpath);
760*33f37583SAndroid Build Coastguard Worker     }
761*33f37583SAndroid Build Coastguard Worker     // realpath might fail in case when dir is a non-existing path. We can
762*33f37583SAndroid Build Coastguard Worker     // ignore non-existing paths.
763*33f37583SAndroid Build Coastguard Worker   }
764*33f37583SAndroid Build Coastguard Worker 
765*33f37583SAndroid Build Coastguard Worker   // Decompressed APEX is also considred factory package
766*33f37583SAndroid Build Coastguard Worker   builtin_dirs.push_back(kApexDecompressedDir);
767*33f37583SAndroid Build Coastguard Worker 
768*33f37583SAndroid Build Coastguard Worker   for (const ApexInfo& package : *factory_packages) {
769*33f37583SAndroid Build Coastguard Worker     bool is_builtin = false;
770*33f37583SAndroid Build Coastguard Worker     for (const auto& dir : builtin_dirs) {
771*33f37583SAndroid Build Coastguard Worker       if (StartsWith(package.modulePath, dir)) {
772*33f37583SAndroid Build Coastguard Worker         is_builtin = true;
773*33f37583SAndroid Build Coastguard Worker       }
774*33f37583SAndroid Build Coastguard Worker     }
775*33f37583SAndroid Build Coastguard Worker     ASSERT_TRUE(is_builtin);
776*33f37583SAndroid Build Coastguard Worker   }
777*33f37583SAndroid Build Coastguard Worker }
778*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,NoPackagesAreBothActiveAndInactive)779*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, NoPackagesAreBothActiveAndInactive) {
780*33f37583SAndroid Build Coastguard Worker   Result<std::vector<ApexInfo>> active_packages = GetActivePackages();
781*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(active_packages);
782*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(active_packages->size() > 0);
783*33f37583SAndroid Build Coastguard Worker   Result<std::vector<ApexInfo>> inactive_packages = GetInactivePackages();
784*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(inactive_packages);
785*33f37583SAndroid Build Coastguard Worker   std::vector<std::string> active_packages_strings =
786*33f37583SAndroid Build Coastguard Worker       GetPackagesStrings(*active_packages);
787*33f37583SAndroid Build Coastguard Worker   std::vector<std::string> inactive_packages_strings =
788*33f37583SAndroid Build Coastguard Worker       GetPackagesStrings(*inactive_packages);
789*33f37583SAndroid Build Coastguard Worker   std::sort(active_packages_strings.begin(), active_packages_strings.end());
790*33f37583SAndroid Build Coastguard Worker   std::sort(inactive_packages_strings.begin(), inactive_packages_strings.end());
791*33f37583SAndroid Build Coastguard Worker   std::vector<std::string> intersection;
792*33f37583SAndroid Build Coastguard Worker   std::set_intersection(
793*33f37583SAndroid Build Coastguard Worker       active_packages_strings.begin(), active_packages_strings.end(),
794*33f37583SAndroid Build Coastguard Worker       inactive_packages_strings.begin(), inactive_packages_strings.end(),
795*33f37583SAndroid Build Coastguard Worker       std::back_inserter(intersection));
796*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(intersection, SizeIs(0));
797*33f37583SAndroid Build Coastguard Worker }
798*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,GetAllPackages)799*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, GetAllPackages) {
800*33f37583SAndroid Build Coastguard Worker   Result<std::vector<ApexInfo>> all_packages = GetAllPackages();
801*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(all_packages);
802*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(all_packages->size() > 0);
803*33f37583SAndroid Build Coastguard Worker   Result<std::vector<ApexInfo>> active_packages = GetActivePackages();
804*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(active_packages);
805*33f37583SAndroid Build Coastguard Worker   std::vector<std::string> active_strings =
806*33f37583SAndroid Build Coastguard Worker       GetPackagesStrings(*active_packages);
807*33f37583SAndroid Build Coastguard Worker   Result<std::vector<ApexInfo>> factory_packages = GetFactoryPackages();
808*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(factory_packages);
809*33f37583SAndroid Build Coastguard Worker   std::vector<std::string> factory_strings =
810*33f37583SAndroid Build Coastguard Worker       GetPackagesStrings(*factory_packages);
811*33f37583SAndroid Build Coastguard Worker   for (ApexInfo& apexInfo : *all_packages) {
812*33f37583SAndroid Build Coastguard Worker     std::string package_string = GetPackageString(apexInfo);
813*33f37583SAndroid Build Coastguard Worker     bool should_be_active =
814*33f37583SAndroid Build Coastguard Worker         std::find(active_strings.begin(), active_strings.end(),
815*33f37583SAndroid Build Coastguard Worker                   package_string) != active_strings.end();
816*33f37583SAndroid Build Coastguard Worker     bool should_be_factory =
817*33f37583SAndroid Build Coastguard Worker         std::find(factory_strings.begin(), factory_strings.end(),
818*33f37583SAndroid Build Coastguard Worker                   package_string) != factory_strings.end();
819*33f37583SAndroid Build Coastguard Worker     ASSERT_EQ(should_be_active, apexInfo.isActive)
820*33f37583SAndroid Build Coastguard Worker         << package_string << " should " << (should_be_active ? "" : "not ")
821*33f37583SAndroid Build Coastguard Worker         << "be active";
822*33f37583SAndroid Build Coastguard Worker     ASSERT_EQ(should_be_factory, apexInfo.isFactory)
823*33f37583SAndroid Build Coastguard Worker         << package_string << " should " << (should_be_factory ? "" : "not ")
824*33f37583SAndroid Build Coastguard Worker         << "be factory";
825*33f37583SAndroid Build Coastguard Worker   }
826*33f37583SAndroid Build Coastguard Worker }
827*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,SubmitSingleSessionTestSuccess)828*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, SubmitSingleSessionTestSuccess) {
829*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
830*33f37583SAndroid Build Coastguard Worker                                       "/data/app-staging/session_123",
831*33f37583SAndroid Build Coastguard Worker                                       "staging_data_file");
832*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
833*33f37583SAndroid Build Coastguard Worker     FAIL() << GetDebugStr(&installer);
834*33f37583SAndroid Build Coastguard Worker   }
835*33f37583SAndroid Build Coastguard Worker 
836*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
837*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
838*33f37583SAndroid Build Coastguard Worker   params.sessionId = 123;
839*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->submitStagedSession(params, &list)))
840*33f37583SAndroid Build Coastguard Worker       << GetDebugStr(&installer);
841*33f37583SAndroid Build Coastguard Worker   EXPECT_EQ(1u, list.apexInfos.size());
842*33f37583SAndroid Build Coastguard Worker   ApexInfo match;
843*33f37583SAndroid Build Coastguard Worker   for (const ApexInfo& info : list.apexInfos) {
844*33f37583SAndroid Build Coastguard Worker     if (info.moduleName == installer.package) {
845*33f37583SAndroid Build Coastguard Worker       match = info;
846*33f37583SAndroid Build Coastguard Worker       break;
847*33f37583SAndroid Build Coastguard Worker     }
848*33f37583SAndroid Build Coastguard Worker   }
849*33f37583SAndroid Build Coastguard Worker 
850*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(installer.package, match.moduleName);
851*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(installer.version, static_cast<uint64_t>(match.versionCode));
852*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(installer.test_file, match.modulePath);
853*33f37583SAndroid Build Coastguard Worker 
854*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo session;
855*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(123, &session)))
856*33f37583SAndroid Build Coastguard Worker       << GetDebugStr(&installer);
857*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo expected = CreateSessionInfo(123);
858*33f37583SAndroid Build Coastguard Worker   expected.isVerified = true;
859*33f37583SAndroid Build Coastguard Worker   EXPECT_THAT(session, SessionInfoEq(expected));
860*33f37583SAndroid Build Coastguard Worker 
861*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->markStagedSessionReady(123)));
862*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(123, &session)))
863*33f37583SAndroid Build Coastguard Worker       << GetDebugStr(&installer);
864*33f37583SAndroid Build Coastguard Worker   expected.isVerified = false;
865*33f37583SAndroid Build Coastguard Worker   expected.isStaged = true;
866*33f37583SAndroid Build Coastguard Worker   EXPECT_THAT(session, SessionInfoEq(expected));
867*33f37583SAndroid Build Coastguard Worker 
868*33f37583SAndroid Build Coastguard Worker   // Call markStagedSessionReady again. Should be a no-op.
869*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->markStagedSessionReady(123)))
870*33f37583SAndroid Build Coastguard Worker       << GetDebugStr(&installer);
871*33f37583SAndroid Build Coastguard Worker 
872*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(123, &session)))
873*33f37583SAndroid Build Coastguard Worker       << GetDebugStr(&installer);
874*33f37583SAndroid Build Coastguard Worker   EXPECT_THAT(session, SessionInfoEq(expected));
875*33f37583SAndroid Build Coastguard Worker 
876*33f37583SAndroid Build Coastguard Worker   // See if the session is reported with getSessions() as well
877*33f37583SAndroid Build Coastguard Worker   std::vector<ApexSessionInfo> sessions;
878*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getSessions(&sessions)))
879*33f37583SAndroid Build Coastguard Worker       << GetDebugStr(&installer);
880*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(sessions, UnorderedElementsAre(SessionInfoEq(expected)));
881*33f37583SAndroid Build Coastguard Worker }
882*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,SubmitSingleSessionTestFail)883*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, SubmitSingleSessionTestFail) {
884*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(
885*33f37583SAndroid Build Coastguard Worker       GetTestFile("apex.apexd_test_corrupt_apex.apex"),
886*33f37583SAndroid Build Coastguard Worker       "/data/app-staging/session_456", "staging_data_file");
887*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
888*33f37583SAndroid Build Coastguard Worker     FAIL() << GetDebugStr(&installer);
889*33f37583SAndroid Build Coastguard Worker   }
890*33f37583SAndroid Build Coastguard Worker 
891*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
892*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
893*33f37583SAndroid Build Coastguard Worker   params.sessionId = 456;
894*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->submitStagedSession(params, &list)))
895*33f37583SAndroid Build Coastguard Worker       << GetDebugStr(&installer);
896*33f37583SAndroid Build Coastguard Worker 
897*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo session;
898*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(456, &session)))
899*33f37583SAndroid Build Coastguard Worker       << GetDebugStr(&installer);
900*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo expected = CreateSessionInfo(-1);
901*33f37583SAndroid Build Coastguard Worker   expected.isUnknown = true;
902*33f37583SAndroid Build Coastguard Worker   EXPECT_THAT(session, SessionInfoEq(expected));
903*33f37583SAndroid Build Coastguard Worker }
904*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,SubmitMultiSessionTestSuccess)905*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, SubmitMultiSessionTestSuccess) {
906*33f37583SAndroid Build Coastguard Worker   // Parent session id: 10
907*33f37583SAndroid Build Coastguard Worker   // Children session ids: 20 30
908*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
909*33f37583SAndroid Build Coastguard Worker                                       "/data/app-staging/session_20",
910*33f37583SAndroid Build Coastguard Worker                                       "staging_data_file");
911*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer2(
912*33f37583SAndroid Build Coastguard Worker       GetTestFile("apex.apexd_test_different_app.apex"),
913*33f37583SAndroid Build Coastguard Worker       "/data/app-staging/session_30", "staging_data_file");
914*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare() || !installer2.Prepare()) {
915*33f37583SAndroid Build Coastguard Worker     FAIL() << GetDebugStr(&installer) << GetDebugStr(&installer2);
916*33f37583SAndroid Build Coastguard Worker   }
917*33f37583SAndroid Build Coastguard Worker 
918*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
919*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
920*33f37583SAndroid Build Coastguard Worker   params.sessionId = 10;
921*33f37583SAndroid Build Coastguard Worker   params.childSessionIds = {20, 30};
922*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->submitStagedSession(params, &list)))
923*33f37583SAndroid Build Coastguard Worker       << GetDebugStr(&installer);
924*33f37583SAndroid Build Coastguard Worker   EXPECT_EQ(2u, list.apexInfos.size());
925*33f37583SAndroid Build Coastguard Worker   ApexInfo match;
926*33f37583SAndroid Build Coastguard Worker   bool package1_found = false;
927*33f37583SAndroid Build Coastguard Worker   bool package2_found = false;
928*33f37583SAndroid Build Coastguard Worker   for (const ApexInfo& info : list.apexInfos) {
929*33f37583SAndroid Build Coastguard Worker     if (info.moduleName == installer.package) {
930*33f37583SAndroid Build Coastguard Worker       ASSERT_EQ(installer.package, info.moduleName);
931*33f37583SAndroid Build Coastguard Worker       ASSERT_EQ(installer.version, static_cast<uint64_t>(info.versionCode));
932*33f37583SAndroid Build Coastguard Worker       ASSERT_EQ(installer.test_file, info.modulePath);
933*33f37583SAndroid Build Coastguard Worker       package1_found = true;
934*33f37583SAndroid Build Coastguard Worker     } else if (info.moduleName == installer2.package) {
935*33f37583SAndroid Build Coastguard Worker       ASSERT_EQ(installer2.package, info.moduleName);
936*33f37583SAndroid Build Coastguard Worker       ASSERT_EQ(installer2.version, static_cast<uint64_t>(info.versionCode));
937*33f37583SAndroid Build Coastguard Worker       ASSERT_EQ(installer2.test_file, info.modulePath);
938*33f37583SAndroid Build Coastguard Worker       package2_found = true;
939*33f37583SAndroid Build Coastguard Worker     } else {
940*33f37583SAndroid Build Coastguard Worker       FAIL() << "Unexpected package found " << info.moduleName
941*33f37583SAndroid Build Coastguard Worker              << GetDebugStr(&installer) << GetDebugStr(&installer2);
942*33f37583SAndroid Build Coastguard Worker     }
943*33f37583SAndroid Build Coastguard Worker   }
944*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(package1_found);
945*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(package2_found);
946*33f37583SAndroid Build Coastguard Worker 
947*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo session;
948*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(10, &session)))
949*33f37583SAndroid Build Coastguard Worker       << GetDebugStr(&installer);
950*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo expected = CreateSessionInfo(10);
951*33f37583SAndroid Build Coastguard Worker   expected.isVerified = true;
952*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(session, SessionInfoEq(expected));
953*33f37583SAndroid Build Coastguard Worker 
954*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->markStagedSessionReady(10)))
955*33f37583SAndroid Build Coastguard Worker       << GetDebugStr(&installer);
956*33f37583SAndroid Build Coastguard Worker 
957*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(10, &session)))
958*33f37583SAndroid Build Coastguard Worker       << GetDebugStr(&installer);
959*33f37583SAndroid Build Coastguard Worker   expected.isVerified = false;
960*33f37583SAndroid Build Coastguard Worker   expected.isStaged = true;
961*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(session, SessionInfoEq(expected));
962*33f37583SAndroid Build Coastguard Worker 
963*33f37583SAndroid Build Coastguard Worker   // Check that temp mounts were cleanded up.
964*33f37583SAndroid Build Coastguard Worker   for (const auto& mount : GetApexMounts()) {
965*33f37583SAndroid Build Coastguard Worker     EXPECT_FALSE(EndsWith(mount, ".tmp")) << "Found temp mount " << mount;
966*33f37583SAndroid Build Coastguard Worker   }
967*33f37583SAndroid Build Coastguard Worker }
968*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,SubmitMultiSessionTestFail)969*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, SubmitMultiSessionTestFail) {
970*33f37583SAndroid Build Coastguard Worker   // Parent session id: 11
971*33f37583SAndroid Build Coastguard Worker   // Children session ids: 21 31
972*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
973*33f37583SAndroid Build Coastguard Worker                                       "/data/app-staging/session_21",
974*33f37583SAndroid Build Coastguard Worker                                       "staging_data_file");
975*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer2(
976*33f37583SAndroid Build Coastguard Worker       GetTestFile("apex.apexd_test_corrupt_apex.apex"),
977*33f37583SAndroid Build Coastguard Worker       "/data/app-staging/session_31", "staging_data_file");
978*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare() || !installer2.Prepare()) {
979*33f37583SAndroid Build Coastguard Worker     FAIL() << GetDebugStr(&installer) << GetDebugStr(&installer2);
980*33f37583SAndroid Build Coastguard Worker   }
981*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
982*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
983*33f37583SAndroid Build Coastguard Worker   params.sessionId = 11;
984*33f37583SAndroid Build Coastguard Worker   params.childSessionIds = {21, 31};
985*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->submitStagedSession(params, &list)))
986*33f37583SAndroid Build Coastguard Worker       << GetDebugStr(&installer);
987*33f37583SAndroid Build Coastguard Worker }
988*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,MarkStagedSessionReadyFail)989*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, MarkStagedSessionReadyFail) {
990*33f37583SAndroid Build Coastguard Worker   // We should fail if we ask information about a session we don't know.
991*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->markStagedSessionReady(666)));
992*33f37583SAndroid Build Coastguard Worker 
993*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo session;
994*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(666, &session)));
995*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo expected = CreateSessionInfo(-1);
996*33f37583SAndroid Build Coastguard Worker   expected.isUnknown = true;
997*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(session, SessionInfoEq(expected));
998*33f37583SAndroid Build Coastguard Worker }
999*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,MarkStagedSessionSuccessfulFailsNoSession)1000*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, MarkStagedSessionSuccessfulFailsNoSession) {
1001*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->markStagedSessionSuccessful(37)));
1002*33f37583SAndroid Build Coastguard Worker 
1003*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo session_info;
1004*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(37, &session_info)));
1005*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo expected = CreateSessionInfo(-1);
1006*33f37583SAndroid Build Coastguard Worker   expected.isUnknown = true;
1007*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(session_info, SessionInfoEq(expected));
1008*33f37583SAndroid Build Coastguard Worker }
1009*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,MarkStagedSessionSuccessfulFailsSessionInWrongState)1010*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, MarkStagedSessionSuccessfulFailsSessionInWrongState) {
1011*33f37583SAndroid Build Coastguard Worker   auto session = CreateSession(73);
1012*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session);
1013*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(
1014*33f37583SAndroid Build Coastguard Worker       session->UpdateStateAndCommit(::apex::proto::SessionState::STAGED));
1015*33f37583SAndroid Build Coastguard Worker 
1016*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->markStagedSessionSuccessful(73)));
1017*33f37583SAndroid Build Coastguard Worker 
1018*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo session_info;
1019*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(73, &session_info)));
1020*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo expected = CreateSessionInfo(73);
1021*33f37583SAndroid Build Coastguard Worker   expected.isStaged = true;
1022*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(session_info, SessionInfoEq(expected));
1023*33f37583SAndroid Build Coastguard Worker }
1024*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,MarkStagedSessionSuccessfulActivatedSession)1025*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, MarkStagedSessionSuccessfulActivatedSession) {
1026*33f37583SAndroid Build Coastguard Worker   auto session = CreateSession(239);
1027*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session);
1028*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(
1029*33f37583SAndroid Build Coastguard Worker       session->UpdateStateAndCommit(::apex::proto::SessionState::ACTIVATED));
1030*33f37583SAndroid Build Coastguard Worker 
1031*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->markStagedSessionSuccessful(239)));
1032*33f37583SAndroid Build Coastguard Worker 
1033*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo session_info;
1034*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(239, &session_info)));
1035*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo expected = CreateSessionInfo(239);
1036*33f37583SAndroid Build Coastguard Worker   expected.isSuccess = true;
1037*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(session_info, SessionInfoEq(expected));
1038*33f37583SAndroid Build Coastguard Worker }
1039*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,MarkStagedSessionSuccessfulNoOp)1040*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, MarkStagedSessionSuccessfulNoOp) {
1041*33f37583SAndroid Build Coastguard Worker   auto session = CreateSession(1543);
1042*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session);
1043*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(
1044*33f37583SAndroid Build Coastguard Worker       session->UpdateStateAndCommit(::apex::proto::SessionState::SUCCESS));
1045*33f37583SAndroid Build Coastguard Worker 
1046*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->markStagedSessionSuccessful(1543)));
1047*33f37583SAndroid Build Coastguard Worker 
1048*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo session_info;
1049*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(1543, &session_info)));
1050*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo expected = CreateSessionInfo(1543);
1051*33f37583SAndroid Build Coastguard Worker   expected.isSuccess = true;
1052*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(session_info, SessionInfoEq(expected));
1053*33f37583SAndroid Build Coastguard Worker }
1054*33f37583SAndroid Build Coastguard Worker 
1055*33f37583SAndroid Build Coastguard Worker // Should be able to abort individual staged session
TEST_F(ApexServiceTest,AbortStagedSession)1056*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, AbortStagedSession) {
1057*33f37583SAndroid Build Coastguard Worker   auto session1 = CreateSession(239);
1058*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session1->UpdateStateAndCommit(SessionState::VERIFIED));
1059*33f37583SAndroid Build Coastguard Worker   auto session2 = CreateSession(240);
1060*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session2->UpdateStateAndCommit(SessionState::STAGED));
1061*33f37583SAndroid Build Coastguard Worker 
1062*33f37583SAndroid Build Coastguard Worker   std::vector<ApexSessionInfo> sessions;
1063*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getSessions(&sessions)));
1064*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(2u, sessions.size());
1065*33f37583SAndroid Build Coastguard Worker 
1066*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->abortStagedSession(239)));
1067*33f37583SAndroid Build Coastguard Worker 
1068*33f37583SAndroid Build Coastguard Worker   sessions.clear();
1069*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getSessions(&sessions)));
1070*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo expected = CreateSessionInfo(240);
1071*33f37583SAndroid Build Coastguard Worker   expected.isStaged = true;
1072*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(sessions, UnorderedElementsAre(SessionInfoEq(expected)));
1073*33f37583SAndroid Build Coastguard Worker }
1074*33f37583SAndroid Build Coastguard Worker 
1075*33f37583SAndroid Build Coastguard Worker // abortStagedSession should not abort activated session
TEST_F(ApexServiceTest,AbortStagedSessionActivatedFail)1076*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, AbortStagedSessionActivatedFail) {
1077*33f37583SAndroid Build Coastguard Worker   auto session1 = CreateSession(239);
1078*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session1->UpdateStateAndCommit(SessionState::ACTIVATED));
1079*33f37583SAndroid Build Coastguard Worker   auto session2 = CreateSession(240);
1080*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session2->UpdateStateAndCommit(SessionState::STAGED));
1081*33f37583SAndroid Build Coastguard Worker 
1082*33f37583SAndroid Build Coastguard Worker   std::vector<ApexSessionInfo> sessions;
1083*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getSessions(&sessions)));
1084*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(2u, sessions.size());
1085*33f37583SAndroid Build Coastguard Worker 
1086*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->abortStagedSession(239)));
1087*33f37583SAndroid Build Coastguard Worker 
1088*33f37583SAndroid Build Coastguard Worker   sessions.clear();
1089*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getSessions(&sessions)));
1090*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo expected1 = CreateSessionInfo(239);
1091*33f37583SAndroid Build Coastguard Worker   expected1.isActivated = true;
1092*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo expected2 = CreateSessionInfo(240);
1093*33f37583SAndroid Build Coastguard Worker   expected2.isStaged = true;
1094*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(sessions, UnorderedElementsAre(SessionInfoEq(expected1),
1095*33f37583SAndroid Build Coastguard Worker                                              SessionInfoEq(expected2)));
1096*33f37583SAndroid Build Coastguard Worker }
1097*33f37583SAndroid Build Coastguard Worker 
1098*33f37583SAndroid Build Coastguard Worker // Only finalized sessions should be deleted on DeleteFinalizedSessions()
TEST_F(ApexServiceTest,DeleteFinalizedSessions)1099*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, DeleteFinalizedSessions) {
1100*33f37583SAndroid Build Coastguard Worker   // Fetch list of all session state
1101*33f37583SAndroid Build Coastguard Worker   std::vector<SessionState::State> states;
1102*33f37583SAndroid Build Coastguard Worker   for (int i = SessionState::State_MIN; i < SessionState::State_MAX; i++) {
1103*33f37583SAndroid Build Coastguard Worker     if (!SessionState::State_IsValid(i)) {
1104*33f37583SAndroid Build Coastguard Worker       continue;
1105*33f37583SAndroid Build Coastguard Worker     }
1106*33f37583SAndroid Build Coastguard Worker     states.push_back(SessionState::State(i));
1107*33f37583SAndroid Build Coastguard Worker   }
1108*33f37583SAndroid Build Coastguard Worker 
1109*33f37583SAndroid Build Coastguard Worker   // For every session state, create a new session. This is to verify we only
1110*33f37583SAndroid Build Coastguard Worker   // delete sessions in final state.
1111*33f37583SAndroid Build Coastguard Worker   auto nonFinalSessions = 0u;
1112*33f37583SAndroid Build Coastguard Worker   for (auto i = 0u; i < states.size(); i++) {
1113*33f37583SAndroid Build Coastguard Worker     auto session = CreateSession(230 + i);
1114*33f37583SAndroid Build Coastguard Worker     SessionState::State state = states[i];
1115*33f37583SAndroid Build Coastguard Worker     ASSERT_RESULT_OK(session->UpdateStateAndCommit(state));
1116*33f37583SAndroid Build Coastguard Worker     if (!session->IsFinalized()) {
1117*33f37583SAndroid Build Coastguard Worker       nonFinalSessions++;
1118*33f37583SAndroid Build Coastguard Worker     }
1119*33f37583SAndroid Build Coastguard Worker   }
1120*33f37583SAndroid Build Coastguard Worker   std::vector<ApexSession> sessions = session_manager_->GetSessions();
1121*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(states.size(), sessions.size());
1122*33f37583SAndroid Build Coastguard Worker 
1123*33f37583SAndroid Build Coastguard Worker   // Now try cleaning up all finalized sessions
1124*33f37583SAndroid Build Coastguard Worker   session_manager_->DeleteFinalizedSessions();
1125*33f37583SAndroid Build Coastguard Worker   sessions = session_manager_->GetSessions();
1126*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(nonFinalSessions, sessions.size());
1127*33f37583SAndroid Build Coastguard Worker 
1128*33f37583SAndroid Build Coastguard Worker   // Verify only finalized sessions have been deleted
1129*33f37583SAndroid Build Coastguard Worker   for (auto& session : sessions) {
1130*33f37583SAndroid Build Coastguard Worker     ASSERT_FALSE(session.IsFinalized());
1131*33f37583SAndroid Build Coastguard Worker   }
1132*33f37583SAndroid Build Coastguard Worker }
1133*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,BackupActivePackages)1134*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, BackupActivePackages) {
1135*33f37583SAndroid Build Coastguard Worker   if (supports_fs_checkpointing_) {
1136*33f37583SAndroid Build Coastguard Worker     GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
1137*33f37583SAndroid Build Coastguard Worker   }
1138*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer1(GetTestFile("apex.apexd_test.apex"));
1139*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer2(
1140*33f37583SAndroid Build Coastguard Worker       GetTestFile("apex.apexd_test_different_app.apex"));
1141*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer3(GetTestFile("apex.apexd_test_v2.apex"),
1142*33f37583SAndroid Build Coastguard Worker                                        "/data/app-staging/session_23",
1143*33f37583SAndroid Build Coastguard Worker                                        "staging_data_file");
1144*33f37583SAndroid Build Coastguard Worker 
1145*33f37583SAndroid Build Coastguard Worker   if (!installer1.Prepare() || !installer2.Prepare() || !installer3.Prepare()) {
1146*33f37583SAndroid Build Coastguard Worker     return;
1147*33f37583SAndroid Build Coastguard Worker   }
1148*33f37583SAndroid Build Coastguard Worker 
1149*33f37583SAndroid Build Coastguard Worker   // Activate some packages, in order to backup them later.
1150*33f37583SAndroid Build Coastguard Worker   std::vector<std::string> pkgs = {installer1.test_file, installer2.test_file};
1151*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->stagePackages(pkgs)));
1152*33f37583SAndroid Build Coastguard Worker 
1153*33f37583SAndroid Build Coastguard Worker   // Make sure that /data/apex/active has activated packages.
1154*33f37583SAndroid Build Coastguard Worker   auto active_pkgs = ReadEntireDir(kActiveApexPackagesDataDir);
1155*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(active_pkgs);
1156*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(*active_pkgs,
1157*33f37583SAndroid Build Coastguard Worker               UnorderedElementsAre(installer1.test_installed_file,
1158*33f37583SAndroid Build Coastguard Worker                                    installer2.test_installed_file));
1159*33f37583SAndroid Build Coastguard Worker 
1160*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
1161*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
1162*33f37583SAndroid Build Coastguard Worker   params.sessionId = 23;
1163*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->submitStagedSession(params, &list)));
1164*33f37583SAndroid Build Coastguard Worker 
1165*33f37583SAndroid Build Coastguard Worker   auto backups = ReadEntireDir(kApexBackupDir);
1166*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(backups);
1167*33f37583SAndroid Build Coastguard Worker   auto backup1 =
1168*33f37583SAndroid Build Coastguard Worker       StringPrintf("%s/com.android.apex.test_package@1.apex", kApexBackupDir);
1169*33f37583SAndroid Build Coastguard Worker   auto backup2 =
1170*33f37583SAndroid Build Coastguard Worker       StringPrintf("%s/com.android.apex.test_package_2@1.apex", kApexBackupDir);
1171*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(*backups, UnorderedElementsAre(backup1, backup2));
1172*33f37583SAndroid Build Coastguard Worker }
1173*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,BackupActivePackagesClearsPreviousBackup)1174*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, BackupActivePackagesClearsPreviousBackup) {
1175*33f37583SAndroid Build Coastguard Worker   if (supports_fs_checkpointing_) {
1176*33f37583SAndroid Build Coastguard Worker     GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
1177*33f37583SAndroid Build Coastguard Worker   }
1178*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer1(GetTestFile("apex.apexd_test.apex"));
1179*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer2(
1180*33f37583SAndroid Build Coastguard Worker       GetTestFile("apex.apexd_test_different_app.apex"));
1181*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer3(GetTestFile("apex.apexd_test_v2.apex"),
1182*33f37583SAndroid Build Coastguard Worker                                        "/data/app-staging/session_43",
1183*33f37583SAndroid Build Coastguard Worker                                        "staging_data_file");
1184*33f37583SAndroid Build Coastguard Worker 
1185*33f37583SAndroid Build Coastguard Worker   if (!installer1.Prepare() || !installer2.Prepare() || !installer3.Prepare()) {
1186*33f37583SAndroid Build Coastguard Worker     return;
1187*33f37583SAndroid Build Coastguard Worker   }
1188*33f37583SAndroid Build Coastguard Worker 
1189*33f37583SAndroid Build Coastguard Worker   // Make sure /data/apex/backups exists.
1190*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(CreateDirIfNeeded(std::string(kApexBackupDir), 0700));
1191*33f37583SAndroid Build Coastguard Worker   // Create some bogus files in /data/apex/backups.
1192*33f37583SAndroid Build Coastguard Worker   std::ofstream old_backup(StringPrintf("%s/file1", kApexBackupDir));
1193*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(old_backup.good());
1194*33f37583SAndroid Build Coastguard Worker   old_backup.close();
1195*33f37583SAndroid Build Coastguard Worker 
1196*33f37583SAndroid Build Coastguard Worker   std::vector<std::string> pkgs = {installer1.test_file, installer2.test_file};
1197*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->stagePackages(pkgs)));
1198*33f37583SAndroid Build Coastguard Worker 
1199*33f37583SAndroid Build Coastguard Worker   // Make sure that /data/apex/active has activated packages.
1200*33f37583SAndroid Build Coastguard Worker   auto active_pkgs = ReadEntireDir(kActiveApexPackagesDataDir);
1201*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(active_pkgs);
1202*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(*active_pkgs,
1203*33f37583SAndroid Build Coastguard Worker               UnorderedElementsAre(installer1.test_installed_file,
1204*33f37583SAndroid Build Coastguard Worker                                    installer2.test_installed_file));
1205*33f37583SAndroid Build Coastguard Worker 
1206*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
1207*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
1208*33f37583SAndroid Build Coastguard Worker   params.sessionId = 43;
1209*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->submitStagedSession(params, &list)));
1210*33f37583SAndroid Build Coastguard Worker 
1211*33f37583SAndroid Build Coastguard Worker   auto backups = ReadEntireDir(kApexBackupDir);
1212*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(backups);
1213*33f37583SAndroid Build Coastguard Worker   auto backup1 =
1214*33f37583SAndroid Build Coastguard Worker       StringPrintf("%s/com.android.apex.test_package@1.apex", kApexBackupDir);
1215*33f37583SAndroid Build Coastguard Worker   auto backup2 =
1216*33f37583SAndroid Build Coastguard Worker       StringPrintf("%s/com.android.apex.test_package_2@1.apex", kApexBackupDir);
1217*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(*backups, UnorderedElementsAre(backup1, backup2));
1218*33f37583SAndroid Build Coastguard Worker }
1219*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,BackupActivePackagesZeroActivePackages)1220*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, BackupActivePackagesZeroActivePackages) {
1221*33f37583SAndroid Build Coastguard Worker   if (supports_fs_checkpointing_) {
1222*33f37583SAndroid Build Coastguard Worker     GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
1223*33f37583SAndroid Build Coastguard Worker   }
1224*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"),
1225*33f37583SAndroid Build Coastguard Worker                                       "/data/app-staging/session_41",
1226*33f37583SAndroid Build Coastguard Worker                                       "staging_data_file");
1227*33f37583SAndroid Build Coastguard Worker 
1228*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1229*33f37583SAndroid Build Coastguard Worker     return;
1230*33f37583SAndroid Build Coastguard Worker   }
1231*33f37583SAndroid Build Coastguard Worker 
1232*33f37583SAndroid Build Coastguard Worker   // Make sure that /data/apex/active exists and is empty
1233*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(
1234*33f37583SAndroid Build Coastguard Worker       CreateDirIfNeeded(std::string(kActiveApexPackagesDataDir), 0755));
1235*33f37583SAndroid Build Coastguard Worker   auto active_pkgs = ReadEntireDir(kActiveApexPackagesDataDir);
1236*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(active_pkgs);
1237*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(0u, active_pkgs->size());
1238*33f37583SAndroid Build Coastguard Worker 
1239*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
1240*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
1241*33f37583SAndroid Build Coastguard Worker   params.sessionId = 41;
1242*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->submitStagedSession(params, &list)));
1243*33f37583SAndroid Build Coastguard Worker 
1244*33f37583SAndroid Build Coastguard Worker   auto backups = ReadEntireDir(kApexBackupDir);
1245*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(backups);
1246*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(0u, backups->size());
1247*33f37583SAndroid Build Coastguard Worker }
1248*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,ActivePackagesDirEmpty)1249*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, ActivePackagesDirEmpty) {
1250*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"),
1251*33f37583SAndroid Build Coastguard Worker                                       "/data/app-staging/session_41",
1252*33f37583SAndroid Build Coastguard Worker                                       "staging_data_file");
1253*33f37583SAndroid Build Coastguard Worker 
1254*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1255*33f37583SAndroid Build Coastguard Worker     return;
1256*33f37583SAndroid Build Coastguard Worker   }
1257*33f37583SAndroid Build Coastguard Worker 
1258*33f37583SAndroid Build Coastguard Worker   // Make sure that /data/apex/active is empty
1259*33f37583SAndroid Build Coastguard Worker   DeleteDirContent(kActiveApexPackagesDataDir);
1260*33f37583SAndroid Build Coastguard Worker 
1261*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
1262*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
1263*33f37583SAndroid Build Coastguard Worker   params.sessionId = 41;
1264*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->submitStagedSession(params, &list)));
1265*33f37583SAndroid Build Coastguard Worker 
1266*33f37583SAndroid Build Coastguard Worker   if (!supports_fs_checkpointing_) {
1267*33f37583SAndroid Build Coastguard Worker     auto backups = ReadEntireDir(kApexBackupDir);
1268*33f37583SAndroid Build Coastguard Worker     ASSERT_RESULT_OK(backups);
1269*33f37583SAndroid Build Coastguard Worker     ASSERT_EQ(0u, backups->size());
1270*33f37583SAndroid Build Coastguard Worker   }
1271*33f37583SAndroid Build Coastguard Worker }
1272*33f37583SAndroid Build Coastguard Worker 
1273*33f37583SAndroid Build Coastguard Worker class ApexServiceRevertTest : public ApexServiceTest {
1274*33f37583SAndroid Build Coastguard Worker  protected:
SetUp()1275*33f37583SAndroid Build Coastguard Worker   void SetUp() override { ApexServiceTest::SetUp(); }
1276*33f37583SAndroid Build Coastguard Worker 
PrepareBackup(const std::vector<std::string> & pkgs)1277*33f37583SAndroid Build Coastguard Worker   void PrepareBackup(const std::vector<std::string>& pkgs) {
1278*33f37583SAndroid Build Coastguard Worker     ASSERT_RESULT_OK(CreateDirIfNeeded(std::string(kApexBackupDir), 0700));
1279*33f37583SAndroid Build Coastguard Worker     for (const auto& pkg : pkgs) {
1280*33f37583SAndroid Build Coastguard Worker       PrepareTestApexForInstall installer(pkg);
1281*33f37583SAndroid Build Coastguard Worker       ASSERT_TRUE(installer.Prepare()) << " failed to prepare " << pkg;
1282*33f37583SAndroid Build Coastguard Worker       const std::string& from = installer.test_file;
1283*33f37583SAndroid Build Coastguard Worker       std::string to = std::string(kApexBackupDir) + "/" + installer.package +
1284*33f37583SAndroid Build Coastguard Worker                        "@" + std::to_string(installer.version) + ".apex";
1285*33f37583SAndroid Build Coastguard Worker       std::error_code ec;
1286*33f37583SAndroid Build Coastguard Worker       fs::copy(fs::path(from), fs::path(to),
1287*33f37583SAndroid Build Coastguard Worker                fs::copy_options::create_hard_links, ec);
1288*33f37583SAndroid Build Coastguard Worker       ASSERT_FALSE(ec) << "Failed to copy " << from << " to " << to << " : "
1289*33f37583SAndroid Build Coastguard Worker                        << ec;
1290*33f37583SAndroid Build Coastguard Worker     }
1291*33f37583SAndroid Build Coastguard Worker   }
1292*33f37583SAndroid Build Coastguard Worker 
CheckActiveApexContents(const std::vector<std::string> & expected_pkgs)1293*33f37583SAndroid Build Coastguard Worker   void CheckActiveApexContents(const std::vector<std::string>& expected_pkgs) {
1294*33f37583SAndroid Build Coastguard Worker     // First check that /data/apex/active exists and has correct permissions.
1295*33f37583SAndroid Build Coastguard Worker     struct stat sd;
1296*33f37583SAndroid Build Coastguard Worker     ASSERT_EQ(0, stat(kActiveApexPackagesDataDir, &sd));
1297*33f37583SAndroid Build Coastguard Worker     ASSERT_EQ(0755u, sd.st_mode & ALLPERMS);
1298*33f37583SAndroid Build Coastguard Worker 
1299*33f37583SAndroid Build Coastguard Worker     // Now read content and check it contains expected values.
1300*33f37583SAndroid Build Coastguard Worker     auto active_pkgs = ReadEntireDir(kActiveApexPackagesDataDir);
1301*33f37583SAndroid Build Coastguard Worker     ASSERT_RESULT_OK(active_pkgs);
1302*33f37583SAndroid Build Coastguard Worker     ASSERT_THAT(*active_pkgs, UnorderedElementsAreArray(expected_pkgs));
1303*33f37583SAndroid Build Coastguard Worker   }
1304*33f37583SAndroid Build Coastguard Worker };
1305*33f37583SAndroid Build Coastguard Worker 
1306*33f37583SAndroid Build Coastguard Worker // Should be able to revert activated sessions
TEST_F(ApexServiceRevertTest,RevertActiveSessionsSuccessful)1307*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceRevertTest, RevertActiveSessionsSuccessful) {
1308*33f37583SAndroid Build Coastguard Worker   if (supports_fs_checkpointing_) {
1309*33f37583SAndroid Build Coastguard Worker     GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
1310*33f37583SAndroid Build Coastguard Worker   }
1311*33f37583SAndroid Build Coastguard Worker 
1312*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"));
1313*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1314*33f37583SAndroid Build Coastguard Worker     return;
1315*33f37583SAndroid Build Coastguard Worker   }
1316*33f37583SAndroid Build Coastguard Worker 
1317*33f37583SAndroid Build Coastguard Worker   auto session = CreateSession(1543);
1318*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session);
1319*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session->UpdateStateAndCommit(SessionState::ACTIVATED));
1320*33f37583SAndroid Build Coastguard Worker 
1321*33f37583SAndroid Build Coastguard Worker   // Make sure /data/apex/active is non-empty.
1322*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
1323*33f37583SAndroid Build Coastguard Worker 
1324*33f37583SAndroid Build Coastguard Worker   PrepareBackup({GetTestFile("apex.apexd_test.apex")});
1325*33f37583SAndroid Build Coastguard Worker 
1326*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->revertActiveSessions()));
1327*33f37583SAndroid Build Coastguard Worker 
1328*33f37583SAndroid Build Coastguard Worker   auto pkg = StringPrintf("%s/com.android.apex.test_package@1.apex",
1329*33f37583SAndroid Build Coastguard Worker                           kActiveApexPackagesDataDir);
1330*33f37583SAndroid Build Coastguard Worker   SCOPED_TRACE("");
1331*33f37583SAndroid Build Coastguard Worker   CheckActiveApexContents({pkg});
1332*33f37583SAndroid Build Coastguard Worker }
1333*33f37583SAndroid Build Coastguard Worker 
1334*33f37583SAndroid Build Coastguard Worker // Calling revertActiveSessions should not restore backup on checkpointing
1335*33f37583SAndroid Build Coastguard Worker // devices
TEST_F(ApexServiceRevertTest,RevertActiveSessionsDoesNotRestoreBackupIfCheckpointingSupported)1336*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceRevertTest,
1337*33f37583SAndroid Build Coastguard Worker        RevertActiveSessionsDoesNotRestoreBackupIfCheckpointingSupported) {
1338*33f37583SAndroid Build Coastguard Worker   if (!supports_fs_checkpointing_) {
1339*33f37583SAndroid Build Coastguard Worker     GTEST_SKIP() << "Can't run if filesystem checkpointing is not supported";
1340*33f37583SAndroid Build Coastguard Worker   }
1341*33f37583SAndroid Build Coastguard Worker 
1342*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"));
1343*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1344*33f37583SAndroid Build Coastguard Worker     return;
1345*33f37583SAndroid Build Coastguard Worker   }
1346*33f37583SAndroid Build Coastguard Worker 
1347*33f37583SAndroid Build Coastguard Worker   auto session = CreateSession(1543);
1348*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session);
1349*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session->UpdateStateAndCommit(SessionState::ACTIVATED));
1350*33f37583SAndroid Build Coastguard Worker 
1351*33f37583SAndroid Build Coastguard Worker   // Make sure /data/apex/active is non-empty.
1352*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
1353*33f37583SAndroid Build Coastguard Worker 
1354*33f37583SAndroid Build Coastguard Worker   PrepareBackup({GetTestFile("apex.apexd_test.apex")});
1355*33f37583SAndroid Build Coastguard Worker 
1356*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->revertActiveSessions()));
1357*33f37583SAndroid Build Coastguard Worker 
1358*33f37583SAndroid Build Coastguard Worker   // Check that active apexes were not reverted.
1359*33f37583SAndroid Build Coastguard Worker   auto pkg = StringPrintf("%s/com.android.apex.test_package@2.apex",
1360*33f37583SAndroid Build Coastguard Worker                           kActiveApexPackagesDataDir);
1361*33f37583SAndroid Build Coastguard Worker   SCOPED_TRACE("");
1362*33f37583SAndroid Build Coastguard Worker   CheckActiveApexContents({pkg});
1363*33f37583SAndroid Build Coastguard Worker }
1364*33f37583SAndroid Build Coastguard Worker 
1365*33f37583SAndroid Build Coastguard Worker // Should fail to revert active sessions when there are none
TEST_F(ApexServiceRevertTest,RevertActiveSessionsWithoutActiveSessions)1366*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceRevertTest, RevertActiveSessionsWithoutActiveSessions) {
1367*33f37583SAndroid Build Coastguard Worker   // This test simulates a situation that should never happen on user builds:
1368*33f37583SAndroid Build Coastguard Worker   // revertActiveSessions was called, but there were no active sessions.
1369*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"));
1370*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1371*33f37583SAndroid Build Coastguard Worker     return;
1372*33f37583SAndroid Build Coastguard Worker   }
1373*33f37583SAndroid Build Coastguard Worker 
1374*33f37583SAndroid Build Coastguard Worker   // Make sure /data/apex/active is non-empty.
1375*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
1376*33f37583SAndroid Build Coastguard Worker 
1377*33f37583SAndroid Build Coastguard Worker   PrepareBackup({GetTestFile("apex.apexd_test.apex")});
1378*33f37583SAndroid Build Coastguard Worker 
1379*33f37583SAndroid Build Coastguard Worker   // Even though backup is there, no sessions are active, hence revert request
1380*33f37583SAndroid Build Coastguard Worker   // should fail.
1381*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->revertActiveSessions()));
1382*33f37583SAndroid Build Coastguard Worker }
1383*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceRevertTest,RevertFailsNoBackupFolder)1384*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceRevertTest, RevertFailsNoBackupFolder) {
1385*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->revertActiveSessions()));
1386*33f37583SAndroid Build Coastguard Worker }
1387*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceRevertTest,RevertFailsNoActivePackagesFolder)1388*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceRevertTest, RevertFailsNoActivePackagesFolder) {
1389*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"));
1390*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->revertActiveSessions()));
1391*33f37583SAndroid Build Coastguard Worker }
1392*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceRevertTest,MarkStagedSessionSuccessfulCleanupBackup)1393*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceRevertTest, MarkStagedSessionSuccessfulCleanupBackup) {
1394*33f37583SAndroid Build Coastguard Worker   PrepareBackup({GetTestFile("apex.apexd_test.apex"),
1395*33f37583SAndroid Build Coastguard Worker                  GetTestFile("apex.apexd_test_different_app.apex")});
1396*33f37583SAndroid Build Coastguard Worker 
1397*33f37583SAndroid Build Coastguard Worker   auto session = CreateSession(101);
1398*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session);
1399*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session->UpdateStateAndCommit(SessionState::ACTIVATED));
1400*33f37583SAndroid Build Coastguard Worker 
1401*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->markStagedSessionSuccessful(101)));
1402*33f37583SAndroid Build Coastguard Worker 
1403*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(fs::is_empty(fs::path(kApexBackupDir)));
1404*33f37583SAndroid Build Coastguard Worker }
1405*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceRevertTest,ResumesRevert)1406*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceRevertTest, ResumesRevert) {
1407*33f37583SAndroid Build Coastguard Worker   if (supports_fs_checkpointing_) {
1408*33f37583SAndroid Build Coastguard Worker     GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
1409*33f37583SAndroid Build Coastguard Worker   }
1410*33f37583SAndroid Build Coastguard Worker   PrepareBackup({GetTestFile("apex.apexd_test.apex"),
1411*33f37583SAndroid Build Coastguard Worker                  GetTestFile("apex.apexd_test_different_app.apex")});
1412*33f37583SAndroid Build Coastguard Worker 
1413*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"));
1414*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1415*33f37583SAndroid Build Coastguard Worker     return;
1416*33f37583SAndroid Build Coastguard Worker   }
1417*33f37583SAndroid Build Coastguard Worker 
1418*33f37583SAndroid Build Coastguard Worker   // Make sure /data/apex/active is non-empty.
1419*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
1420*33f37583SAndroid Build Coastguard Worker 
1421*33f37583SAndroid Build Coastguard Worker   auto session = CreateSession(17239);
1422*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session);
1423*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(
1424*33f37583SAndroid Build Coastguard Worker       session->UpdateStateAndCommit(SessionState::REVERT_IN_PROGRESS));
1425*33f37583SAndroid Build Coastguard Worker 
1426*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->resumeRevertIfNeeded()));
1427*33f37583SAndroid Build Coastguard Worker 
1428*33f37583SAndroid Build Coastguard Worker   auto pkg1 = StringPrintf("%s/com.android.apex.test_package@1.apex",
1429*33f37583SAndroid Build Coastguard Worker                            kActiveApexPackagesDataDir);
1430*33f37583SAndroid Build Coastguard Worker   auto pkg2 = StringPrintf("%s/com.android.apex.test_package_2@1.apex",
1431*33f37583SAndroid Build Coastguard Worker                            kActiveApexPackagesDataDir);
1432*33f37583SAndroid Build Coastguard Worker   SCOPED_TRACE("");
1433*33f37583SAndroid Build Coastguard Worker   CheckActiveApexContents({pkg1, pkg2});
1434*33f37583SAndroid Build Coastguard Worker 
1435*33f37583SAndroid Build Coastguard Worker   std::vector<ApexSessionInfo> sessions;
1436*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getSessions(&sessions)));
1437*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo expected = CreateSessionInfo(17239);
1438*33f37583SAndroid Build Coastguard Worker   expected.isReverted = true;
1439*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(sessions, UnorderedElementsAre(SessionInfoEq(expected)));
1440*33f37583SAndroid Build Coastguard Worker }
1441*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceRevertTest,DoesNotResumeRevert)1442*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceRevertTest, DoesNotResumeRevert) {
1443*33f37583SAndroid Build Coastguard Worker   if (supports_fs_checkpointing_) {
1444*33f37583SAndroid Build Coastguard Worker     GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
1445*33f37583SAndroid Build Coastguard Worker   }
1446*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"));
1447*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1448*33f37583SAndroid Build Coastguard Worker     return;
1449*33f37583SAndroid Build Coastguard Worker   }
1450*33f37583SAndroid Build Coastguard Worker 
1451*33f37583SAndroid Build Coastguard Worker   // Make sure /data/apex/active is non-empty.
1452*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
1453*33f37583SAndroid Build Coastguard Worker 
1454*33f37583SAndroid Build Coastguard Worker   auto session = CreateSession(53);
1455*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session);
1456*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session->UpdateStateAndCommit(SessionState::SUCCESS));
1457*33f37583SAndroid Build Coastguard Worker 
1458*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->resumeRevertIfNeeded()));
1459*33f37583SAndroid Build Coastguard Worker 
1460*33f37583SAndroid Build Coastguard Worker   // Check that revert wasn't resumed.
1461*33f37583SAndroid Build Coastguard Worker   auto active_pkgs = ReadEntireDir(kActiveApexPackagesDataDir);
1462*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(active_pkgs);
1463*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(*active_pkgs,
1464*33f37583SAndroid Build Coastguard Worker               UnorderedElementsAre(installer.test_installed_file));
1465*33f37583SAndroid Build Coastguard Worker 
1466*33f37583SAndroid Build Coastguard Worker   std::vector<ApexSessionInfo> sessions;
1467*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getSessions(&sessions)));
1468*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo expected = CreateSessionInfo(53);
1469*33f37583SAndroid Build Coastguard Worker   expected.isSuccess = true;
1470*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(sessions, UnorderedElementsAre(SessionInfoEq(expected)));
1471*33f37583SAndroid Build Coastguard Worker }
1472*33f37583SAndroid Build Coastguard Worker 
1473*33f37583SAndroid Build Coastguard Worker // Should mark sessions as REVERT_FAILED on failed revert
TEST_F(ApexServiceRevertTest,SessionsMarkedAsRevertFailed)1474*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceRevertTest, SessionsMarkedAsRevertFailed) {
1475*33f37583SAndroid Build Coastguard Worker   if (supports_fs_checkpointing_) {
1476*33f37583SAndroid Build Coastguard Worker     GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
1477*33f37583SAndroid Build Coastguard Worker   }
1478*33f37583SAndroid Build Coastguard Worker 
1479*33f37583SAndroid Build Coastguard Worker   auto session = CreateSession(53);
1480*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session);
1481*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session->UpdateStateAndCommit(SessionState::ACTIVATED));
1482*33f37583SAndroid Build Coastguard Worker 
1483*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->revertActiveSessions()));
1484*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo session_info;
1485*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(53, &session_info)));
1486*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo expected = CreateSessionInfo(53);
1487*33f37583SAndroid Build Coastguard Worker   expected.isRevertFailed = true;
1488*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(session_info, SessionInfoEq(expected));
1489*33f37583SAndroid Build Coastguard Worker }
1490*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceRevertTest,RevertFailedStateRevertAttemptFails)1491*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceRevertTest, RevertFailedStateRevertAttemptFails) {
1492*33f37583SAndroid Build Coastguard Worker   if (supports_fs_checkpointing_) {
1493*33f37583SAndroid Build Coastguard Worker     GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
1494*33f37583SAndroid Build Coastguard Worker   }
1495*33f37583SAndroid Build Coastguard Worker 
1496*33f37583SAndroid Build Coastguard Worker   auto session = CreateSession(17239);
1497*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session);
1498*33f37583SAndroid Build Coastguard Worker   ASSERT_RESULT_OK(session->UpdateStateAndCommit(SessionState::REVERT_FAILED));
1499*33f37583SAndroid Build Coastguard Worker 
1500*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->revertActiveSessions()));
1501*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo session_info;
1502*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(17239, &session_info)));
1503*33f37583SAndroid Build Coastguard Worker   ApexSessionInfo expected = CreateSessionInfo(17239);
1504*33f37583SAndroid Build Coastguard Worker   expected.isRevertFailed = true;
1505*33f37583SAndroid Build Coastguard Worker   ASSERT_THAT(session_info, SessionInfoEq(expected));
1506*33f37583SAndroid Build Coastguard Worker }
1507*33f37583SAndroid Build Coastguard Worker 
GetPidOf(const std::string & name)1508*33f37583SAndroid Build Coastguard Worker static pid_t GetPidOf(const std::string& name) {
1509*33f37583SAndroid Build Coastguard Worker   char buf[1024];
1510*33f37583SAndroid Build Coastguard Worker   const std::string cmd = std::string("pidof -s ") + name;
1511*33f37583SAndroid Build Coastguard Worker   FILE* cmd_pipe = popen(cmd.c_str(), "r");  // NOLINT(cert-env33-c): test code
1512*33f37583SAndroid Build Coastguard Worker   if (cmd_pipe == nullptr) {
1513*33f37583SAndroid Build Coastguard Worker     PLOG(ERROR) << "Cannot open pipe for " << cmd;
1514*33f37583SAndroid Build Coastguard Worker     return 0;
1515*33f37583SAndroid Build Coastguard Worker   }
1516*33f37583SAndroid Build Coastguard Worker   if (fgets(buf, 1024, cmd_pipe) == nullptr) {
1517*33f37583SAndroid Build Coastguard Worker     PLOG(ERROR) << "Cannot read pipe for " << cmd;
1518*33f37583SAndroid Build Coastguard Worker     pclose(cmd_pipe);
1519*33f37583SAndroid Build Coastguard Worker     return 0;
1520*33f37583SAndroid Build Coastguard Worker   }
1521*33f37583SAndroid Build Coastguard Worker 
1522*33f37583SAndroid Build Coastguard Worker   pclose(cmd_pipe);
1523*33f37583SAndroid Build Coastguard Worker   return strtoul(buf, nullptr, 10);
1524*33f37583SAndroid Build Coastguard Worker }
1525*33f37583SAndroid Build Coastguard Worker 
ExecInMountNamespaceOf(pid_t pid,const std::function<void (pid_t)> & func)1526*33f37583SAndroid Build Coastguard Worker static void ExecInMountNamespaceOf(pid_t pid,
1527*33f37583SAndroid Build Coastguard Worker                                    const std::function<void(pid_t)>& func) {
1528*33f37583SAndroid Build Coastguard Worker   const std::string my_path = "/proc/self/ns/mnt";
1529*33f37583SAndroid Build Coastguard Worker   android::base::unique_fd my_fd(open(my_path.c_str(), O_RDONLY | O_CLOEXEC));
1530*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(my_fd.get() >= 0);
1531*33f37583SAndroid Build Coastguard Worker 
1532*33f37583SAndroid Build Coastguard Worker   const std::string target_path =
1533*33f37583SAndroid Build Coastguard Worker       std::string("/proc/") + std::to_string(pid) + "/ns/mnt";
1534*33f37583SAndroid Build Coastguard Worker   android::base::unique_fd target_fd(
1535*33f37583SAndroid Build Coastguard Worker       open(target_path.c_str(), O_RDONLY | O_CLOEXEC));
1536*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(target_fd.get() >= 0);
1537*33f37583SAndroid Build Coastguard Worker 
1538*33f37583SAndroid Build Coastguard Worker   int res = setns(target_fd.get(), CLONE_NEWNS);
1539*33f37583SAndroid Build Coastguard Worker   ASSERT_NE(-1, res);
1540*33f37583SAndroid Build Coastguard Worker 
1541*33f37583SAndroid Build Coastguard Worker   func(pid);
1542*33f37583SAndroid Build Coastguard Worker 
1543*33f37583SAndroid Build Coastguard Worker   res = setns(my_fd.get(), CLONE_NEWNS);
1544*33f37583SAndroid Build Coastguard Worker   ASSERT_NE(-1, res);
1545*33f37583SAndroid Build Coastguard Worker }
1546*33f37583SAndroid Build Coastguard Worker 
1547*33f37583SAndroid Build Coastguard Worker // This test case is part of the ApexServiceTest suite to ensure that apexd is
1548*33f37583SAndroid Build Coastguard Worker // running when this test is executed.
TEST_F(ApexServiceTest,ApexdIsInSameMountNamespaceAsInit)1549*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, ApexdIsInSameMountNamespaceAsInit) {
1550*33f37583SAndroid Build Coastguard Worker   std::string ns_apexd;
1551*33f37583SAndroid Build Coastguard Worker   std::string ns_init;
1552*33f37583SAndroid Build Coastguard Worker 
1553*33f37583SAndroid Build Coastguard Worker   ExecInMountNamespaceOf(GetPidOf("apexd"), [&](pid_t /*pid*/) {
1554*33f37583SAndroid Build Coastguard Worker     bool res = android::base::Readlink("/proc/self/ns/mnt", &ns_apexd);
1555*33f37583SAndroid Build Coastguard Worker     ASSERT_TRUE(res);
1556*33f37583SAndroid Build Coastguard Worker   });
1557*33f37583SAndroid Build Coastguard Worker 
1558*33f37583SAndroid Build Coastguard Worker   ExecInMountNamespaceOf(1, [&](pid_t /*pid*/) {
1559*33f37583SAndroid Build Coastguard Worker     bool res = android::base::Readlink("/proc/self/ns/mnt", &ns_init);
1560*33f37583SAndroid Build Coastguard Worker     ASSERT_TRUE(res);
1561*33f37583SAndroid Build Coastguard Worker   });
1562*33f37583SAndroid Build Coastguard Worker 
1563*33f37583SAndroid Build Coastguard Worker   ASSERT_EQ(ns_apexd, ns_init);
1564*33f37583SAndroid Build Coastguard Worker }
1565*33f37583SAndroid Build Coastguard Worker 
1566*33f37583SAndroid Build Coastguard Worker // These are NOT exhaustive list of early processes be should be enough
1567*33f37583SAndroid Build Coastguard Worker static const std::vector<std::string> kEarlyProcesses = {
1568*33f37583SAndroid Build Coastguard Worker     "vold",
1569*33f37583SAndroid Build Coastguard Worker     "logd",
1570*33f37583SAndroid Build Coastguard Worker };
1571*33f37583SAndroid Build Coastguard Worker 
1572*33f37583SAndroid Build Coastguard Worker // This test case is part of the ApexServiceTest suite to ensure that apexd is
1573*33f37583SAndroid Build Coastguard Worker // running when this test is executed.
TEST_F(ApexServiceTest,EarlyProcessesAreInDifferentMountNamespace)1574*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, EarlyProcessesAreInDifferentMountNamespace) {
1575*33f37583SAndroid Build Coastguard Worker   std::string ns_apexd;
1576*33f37583SAndroid Build Coastguard Worker 
1577*33f37583SAndroid Build Coastguard Worker   ExecInMountNamespaceOf(GetPidOf("apexd"), [&](pid_t /*pid*/) {
1578*33f37583SAndroid Build Coastguard Worker     bool res = android::base::Readlink("/proc/self/ns/mnt", &ns_apexd);
1579*33f37583SAndroid Build Coastguard Worker     ASSERT_TRUE(res);
1580*33f37583SAndroid Build Coastguard Worker   });
1581*33f37583SAndroid Build Coastguard Worker 
1582*33f37583SAndroid Build Coastguard Worker   for (const auto& name : kEarlyProcesses) {
1583*33f37583SAndroid Build Coastguard Worker     std::string ns_early_process;
1584*33f37583SAndroid Build Coastguard Worker     ExecInMountNamespaceOf(GetPidOf(name), [&](pid_t /*pid*/) {
1585*33f37583SAndroid Build Coastguard Worker       bool res =
1586*33f37583SAndroid Build Coastguard Worker           android::base::Readlink("/proc/self/ns/mnt", &ns_early_process);
1587*33f37583SAndroid Build Coastguard Worker       ASSERT_TRUE(res);
1588*33f37583SAndroid Build Coastguard Worker     });
1589*33f37583SAndroid Build Coastguard Worker     ASSERT_NE(ns_apexd, ns_early_process);
1590*33f37583SAndroid Build Coastguard Worker   }
1591*33f37583SAndroid Build Coastguard Worker }
1592*33f37583SAndroid Build Coastguard Worker 
TEST(ApexdTest,ApexIsAPrivateMountPoint)1593*33f37583SAndroid Build Coastguard Worker TEST(ApexdTest, ApexIsAPrivateMountPoint) {
1594*33f37583SAndroid Build Coastguard Worker   std::string mountinfo;
1595*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(
1596*33f37583SAndroid Build Coastguard Worker       android::base::ReadFileToString("/proc/self/mountinfo", &mountinfo));
1597*33f37583SAndroid Build Coastguard Worker   bool found_apex_mountpoint = false;
1598*33f37583SAndroid Build Coastguard Worker   for (const auto& line : android::base::Split(mountinfo, "\n")) {
1599*33f37583SAndroid Build Coastguard Worker     std::vector<std::string> tokens = android::base::Split(line, " ");
1600*33f37583SAndroid Build Coastguard Worker     // line format:
1601*33f37583SAndroid Build Coastguard Worker     // mnt_id parent_mnt_id major:minor source target option propagation_type
1602*33f37583SAndroid Build Coastguard Worker     // ex) 33 260:19 / /apex rw,nosuid,nodev -
1603*33f37583SAndroid Build Coastguard Worker     if (tokens.size() >= 7 && tokens[4] == "/apex") {
1604*33f37583SAndroid Build Coastguard Worker       found_apex_mountpoint = true;
1605*33f37583SAndroid Build Coastguard Worker       // Make sure that propagation type is set to - which means private
1606*33f37583SAndroid Build Coastguard Worker       ASSERT_EQ("-", tokens[6]);
1607*33f37583SAndroid Build Coastguard Worker     }
1608*33f37583SAndroid Build Coastguard Worker   }
1609*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(found_apex_mountpoint);
1610*33f37583SAndroid Build Coastguard Worker }
1611*33f37583SAndroid Build Coastguard Worker 
1612*33f37583SAndroid Build Coastguard Worker static const std::vector<std::string> kEarlyApexes = {
1613*33f37583SAndroid Build Coastguard Worker     "/apex/com.android.runtime",
1614*33f37583SAndroid Build Coastguard Worker     "/apex/com.android.tzdata",
1615*33f37583SAndroid Build Coastguard Worker };
1616*33f37583SAndroid Build Coastguard Worker 
TEST(ApexdTest,ApexesAreActivatedForEarlyProcesses)1617*33f37583SAndroid Build Coastguard Worker TEST(ApexdTest, ApexesAreActivatedForEarlyProcesses) {
1618*33f37583SAndroid Build Coastguard Worker   for (const auto& name : kEarlyProcesses) {
1619*33f37583SAndroid Build Coastguard Worker     pid_t pid = GetPidOf(name);
1620*33f37583SAndroid Build Coastguard Worker     const std::string path =
1621*33f37583SAndroid Build Coastguard Worker         std::string("/proc/") + std::to_string(pid) + "/mountinfo";
1622*33f37583SAndroid Build Coastguard Worker     std::string mountinfo;
1623*33f37583SAndroid Build Coastguard Worker     ASSERT_TRUE(android::base::ReadFileToString(path.c_str(), &mountinfo));
1624*33f37583SAndroid Build Coastguard Worker 
1625*33f37583SAndroid Build Coastguard Worker     std::unordered_set<std::string> mountpoints;
1626*33f37583SAndroid Build Coastguard Worker     for (const auto& line : android::base::Split(mountinfo, "\n")) {
1627*33f37583SAndroid Build Coastguard Worker       std::vector<std::string> tokens = android::base::Split(line, " ");
1628*33f37583SAndroid Build Coastguard Worker       // line format:
1629*33f37583SAndroid Build Coastguard Worker       // mnt_id parent_mnt_id major:minor source target option propagation_type
1630*33f37583SAndroid Build Coastguard Worker       // ex) 69 33 7:40 / /apex/com.android.conscrypt ro,nodev,noatime -
1631*33f37583SAndroid Build Coastguard Worker       if (tokens.size() >= 5) {
1632*33f37583SAndroid Build Coastguard Worker         // token[4] is the target mount point
1633*33f37583SAndroid Build Coastguard Worker         mountpoints.emplace(tokens[4]);
1634*33f37583SAndroid Build Coastguard Worker       }
1635*33f37583SAndroid Build Coastguard Worker     }
1636*33f37583SAndroid Build Coastguard Worker     for (const auto& apex_name : kEarlyApexes) {
1637*33f37583SAndroid Build Coastguard Worker       ASSERT_NE(mountpoints.end(), mountpoints.find(apex_name));
1638*33f37583SAndroid Build Coastguard Worker     }
1639*33f37583SAndroid Build Coastguard Worker   }
1640*33f37583SAndroid Build Coastguard Worker }
1641*33f37583SAndroid Build Coastguard Worker 
1642*33f37583SAndroid Build Coastguard Worker class ApexShimUpdateTest : public ApexServiceTest {
1643*33f37583SAndroid Build Coastguard Worker  protected:
SetUp()1644*33f37583SAndroid Build Coastguard Worker   void SetUp() override {
1645*33f37583SAndroid Build Coastguard Worker     ApexServiceTest::SetUp();
1646*33f37583SAndroid Build Coastguard Worker 
1647*33f37583SAndroid Build Coastguard Worker     // Skip test if for some reason shim APEX is missing.
1648*33f37583SAndroid Build Coastguard Worker     std::vector<ApexInfo> list;
1649*33f37583SAndroid Build Coastguard Worker     ASSERT_TRUE(IsOk(service_->getAllPackages(&list)));
1650*33f37583SAndroid Build Coastguard Worker     bool found = std::any_of(list.begin(), list.end(), [](const auto& apex) {
1651*33f37583SAndroid Build Coastguard Worker       return apex.moduleName == "com.android.apex.cts.shim";
1652*33f37583SAndroid Build Coastguard Worker     });
1653*33f37583SAndroid Build Coastguard Worker     if (!found) {
1654*33f37583SAndroid Build Coastguard Worker       GTEST_SKIP() << "Can't find com.android.apex.cts.shim";
1655*33f37583SAndroid Build Coastguard Worker     }
1656*33f37583SAndroid Build Coastguard Worker   }
1657*33f37583SAndroid Build Coastguard Worker };
1658*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexShimUpdateTest,UpdateToV2Success)1659*33f37583SAndroid Build Coastguard Worker TEST_F(ApexShimUpdateTest, UpdateToV2Success) {
1660*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(
1661*33f37583SAndroid Build Coastguard Worker       GetTestFile("com.android.apex.cts.shim.v2.apex"));
1662*33f37583SAndroid Build Coastguard Worker 
1663*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1664*33f37583SAndroid Build Coastguard Worker     FAIL() << GetDebugStr(&installer);
1665*33f37583SAndroid Build Coastguard Worker   }
1666*33f37583SAndroid Build Coastguard Worker 
1667*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
1668*33f37583SAndroid Build Coastguard Worker }
1669*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexShimUpdateTest,SubmitStagedSessionFailureHasPreInstallHook)1670*33f37583SAndroid Build Coastguard Worker TEST_F(ApexShimUpdateTest, SubmitStagedSessionFailureHasPreInstallHook) {
1671*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(
1672*33f37583SAndroid Build Coastguard Worker       GetTestFile("com.android.apex.cts.shim.v2_with_pre_install_hook.apex"),
1673*33f37583SAndroid Build Coastguard Worker       "/data/app-staging/session_23", "staging_data_file");
1674*33f37583SAndroid Build Coastguard Worker 
1675*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1676*33f37583SAndroid Build Coastguard Worker     FAIL() << GetDebugStr(&installer);
1677*33f37583SAndroid Build Coastguard Worker   }
1678*33f37583SAndroid Build Coastguard Worker 
1679*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
1680*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
1681*33f37583SAndroid Build Coastguard Worker   params.sessionId = 23;
1682*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->submitStagedSession(params, &list)));
1683*33f37583SAndroid Build Coastguard Worker }
1684*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexShimUpdateTest,SubmitStagedSessionFailureHasPostInstallHook)1685*33f37583SAndroid Build Coastguard Worker TEST_F(ApexShimUpdateTest, SubmitStagedSessionFailureHasPostInstallHook) {
1686*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(
1687*33f37583SAndroid Build Coastguard Worker       GetTestFile("com.android.apex.cts.shim.v2_with_post_install_hook.apex"),
1688*33f37583SAndroid Build Coastguard Worker       "/data/app-staging/session_43", "staging_data_file");
1689*33f37583SAndroid Build Coastguard Worker 
1690*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1691*33f37583SAndroid Build Coastguard Worker     FAIL() << GetDebugStr(&installer);
1692*33f37583SAndroid Build Coastguard Worker   }
1693*33f37583SAndroid Build Coastguard Worker 
1694*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
1695*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
1696*33f37583SAndroid Build Coastguard Worker   params.sessionId = 43;
1697*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->submitStagedSession(params, &list)));
1698*33f37583SAndroid Build Coastguard Worker }
1699*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexShimUpdateTest,SubmitStagedSessionFailureAdditionalFile)1700*33f37583SAndroid Build Coastguard Worker TEST_F(ApexShimUpdateTest, SubmitStagedSessionFailureAdditionalFile) {
1701*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(
1702*33f37583SAndroid Build Coastguard Worker       GetTestFile("com.android.apex.cts.shim.v2_additional_file.apex"),
1703*33f37583SAndroid Build Coastguard Worker       "/data/app-staging/session_41", "staging_data_file");
1704*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1705*33f37583SAndroid Build Coastguard Worker     FAIL() << GetDebugStr(&installer);
1706*33f37583SAndroid Build Coastguard Worker   }
1707*33f37583SAndroid Build Coastguard Worker 
1708*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
1709*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
1710*33f37583SAndroid Build Coastguard Worker   params.sessionId = 41;
1711*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->submitStagedSession(params, &list)));
1712*33f37583SAndroid Build Coastguard Worker }
1713*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexShimUpdateTest,SubmitStagedSessionFailureAdditionalFolder)1714*33f37583SAndroid Build Coastguard Worker TEST_F(ApexShimUpdateTest, SubmitStagedSessionFailureAdditionalFolder) {
1715*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(
1716*33f37583SAndroid Build Coastguard Worker       GetTestFile("com.android.apex.cts.shim.v2_additional_folder.apex"),
1717*33f37583SAndroid Build Coastguard Worker       "/data/app-staging/session_42", "staging_data_file");
1718*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1719*33f37583SAndroid Build Coastguard Worker     FAIL() << GetDebugStr(&installer);
1720*33f37583SAndroid Build Coastguard Worker   }
1721*33f37583SAndroid Build Coastguard Worker 
1722*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
1723*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
1724*33f37583SAndroid Build Coastguard Worker   params.sessionId = 42;
1725*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->submitStagedSession(params, &list)));
1726*33f37583SAndroid Build Coastguard Worker }
1727*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexShimUpdateTest,UpdateToV1Success)1728*33f37583SAndroid Build Coastguard Worker TEST_F(ApexShimUpdateTest, UpdateToV1Success) {
1729*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(
1730*33f37583SAndroid Build Coastguard Worker       GetTestFile("com.android.apex.cts.shim.apex"));
1731*33f37583SAndroid Build Coastguard Worker 
1732*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1733*33f37583SAndroid Build Coastguard Worker     FAIL() << GetDebugStr(&installer);
1734*33f37583SAndroid Build Coastguard Worker   }
1735*33f37583SAndroid Build Coastguard Worker 
1736*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
1737*33f37583SAndroid Build Coastguard Worker }
1738*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexShimUpdateTest,SubmitStagedSessionV1ShimApexSuccess)1739*33f37583SAndroid Build Coastguard Worker TEST_F(ApexShimUpdateTest, SubmitStagedSessionV1ShimApexSuccess) {
1740*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(
1741*33f37583SAndroid Build Coastguard Worker       GetTestFile("com.android.apex.cts.shim.apex"),
1742*33f37583SAndroid Build Coastguard Worker       "/data/app-staging/session_97", "staging_data_file");
1743*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1744*33f37583SAndroid Build Coastguard Worker     FAIL() << GetDebugStr(&installer);
1745*33f37583SAndroid Build Coastguard Worker   }
1746*33f37583SAndroid Build Coastguard Worker 
1747*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
1748*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
1749*33f37583SAndroid Build Coastguard Worker   params.sessionId = 97;
1750*33f37583SAndroid Build Coastguard Worker   ASSERT_TRUE(IsOk(service_->submitStagedSession(params, &list)));
1751*33f37583SAndroid Build Coastguard Worker }
1752*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,SubmitStagedSessionCorruptApexFails)1753*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, SubmitStagedSessionCorruptApexFails) {
1754*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(
1755*33f37583SAndroid Build Coastguard Worker       GetTestFile("apex.apexd_test_corrupt_apex.apex"),
1756*33f37583SAndroid Build Coastguard Worker       "/data/app-staging/session_57", "staging_data_file");
1757*33f37583SAndroid Build Coastguard Worker 
1758*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1759*33f37583SAndroid Build Coastguard Worker     FAIL() << GetDebugStr(&installer);
1760*33f37583SAndroid Build Coastguard Worker   }
1761*33f37583SAndroid Build Coastguard Worker 
1762*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
1763*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
1764*33f37583SAndroid Build Coastguard Worker   params.sessionId = 57;
1765*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->submitStagedSession(params, &list)));
1766*33f37583SAndroid Build Coastguard Worker }
1767*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,SubmitStagedSessionCorruptApexFailsB146895998)1768*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, SubmitStagedSessionCorruptApexFailsB146895998) {
1769*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("corrupted_b146895998.apex"),
1770*33f37583SAndroid Build Coastguard Worker                                       "/data/app-staging/session_71",
1771*33f37583SAndroid Build Coastguard Worker                                       "staging_data_file");
1772*33f37583SAndroid Build Coastguard Worker 
1773*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1774*33f37583SAndroid Build Coastguard Worker     FAIL() << GetDebugStr(&installer);
1775*33f37583SAndroid Build Coastguard Worker   }
1776*33f37583SAndroid Build Coastguard Worker 
1777*33f37583SAndroid Build Coastguard Worker   ApexInfoList list;
1778*33f37583SAndroid Build Coastguard Worker   ApexSessionParams params;
1779*33f37583SAndroid Build Coastguard Worker   params.sessionId = 71;
1780*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->submitStagedSession(params, &list)));
1781*33f37583SAndroid Build Coastguard Worker }
1782*33f37583SAndroid Build Coastguard Worker 
TEST_F(ApexServiceTest,StageCorruptApexFailsB146895998)1783*33f37583SAndroid Build Coastguard Worker TEST_F(ApexServiceTest, StageCorruptApexFailsB146895998) {
1784*33f37583SAndroid Build Coastguard Worker   PrepareTestApexForInstall installer(GetTestFile("corrupted_b146895998.apex"));
1785*33f37583SAndroid Build Coastguard Worker 
1786*33f37583SAndroid Build Coastguard Worker   if (!installer.Prepare()) {
1787*33f37583SAndroid Build Coastguard Worker     FAIL() << GetDebugStr(&installer);
1788*33f37583SAndroid Build Coastguard Worker   }
1789*33f37583SAndroid Build Coastguard Worker 
1790*33f37583SAndroid Build Coastguard Worker   ASSERT_FALSE(IsOk(service_->stagePackages({installer.test_file})));
1791*33f37583SAndroid Build Coastguard Worker }
1792*33f37583SAndroid Build Coastguard Worker 
1793*33f37583SAndroid Build Coastguard Worker class LogTestToLogcat : public ::testing::EmptyTestEventListener {
OnTestStart(const::testing::TestInfo & test_info)1794*33f37583SAndroid Build Coastguard Worker   void OnTestStart(const ::testing::TestInfo& test_info) override {
1795*33f37583SAndroid Build Coastguard Worker #ifdef __ANDROID__
1796*33f37583SAndroid Build Coastguard Worker     using base::LogId;
1797*33f37583SAndroid Build Coastguard Worker     using base::LogSeverity;
1798*33f37583SAndroid Build Coastguard Worker     using base::StringPrintf;
1799*33f37583SAndroid Build Coastguard Worker     base::LogdLogger l;
1800*33f37583SAndroid Build Coastguard Worker     std::string msg =
1801*33f37583SAndroid Build Coastguard Worker         StringPrintf("=== %s::%s (%s:%d)", test_info.test_suite_name(),
1802*33f37583SAndroid Build Coastguard Worker                      test_info.name(), test_info.file(), test_info.line());
1803*33f37583SAndroid Build Coastguard Worker     l(LogId::MAIN, LogSeverity::INFO, "ApexServiceTestCases", __FILE__,
1804*33f37583SAndroid Build Coastguard Worker       __LINE__, msg.c_str());
1805*33f37583SAndroid Build Coastguard Worker #else
1806*33f37583SAndroid Build Coastguard Worker     UNUSED(test_info);
1807*33f37583SAndroid Build Coastguard Worker #endif
1808*33f37583SAndroid Build Coastguard Worker   }
1809*33f37583SAndroid Build Coastguard Worker };
1810*33f37583SAndroid Build Coastguard Worker 
1811*33f37583SAndroid Build Coastguard Worker }  // namespace apex
1812*33f37583SAndroid Build Coastguard Worker }  // namespace android
1813*33f37583SAndroid Build Coastguard Worker 
main(int argc,char ** argv)1814*33f37583SAndroid Build Coastguard Worker int main(int argc, char** argv) {
1815*33f37583SAndroid Build Coastguard Worker   ::testing::InitGoogleTest(&argc, argv);
1816*33f37583SAndroid Build Coastguard Worker   android::base::InitLogging(argv, &android::base::StderrLogger);
1817*33f37583SAndroid Build Coastguard Worker   android::base::SetMinimumLogSeverity(android::base::VERBOSE);
1818*33f37583SAndroid Build Coastguard Worker   ::testing::UnitTest::GetInstance()->listeners().Append(
1819*33f37583SAndroid Build Coastguard Worker       new android::apex::LogTestToLogcat());
1820*33f37583SAndroid Build Coastguard Worker   return RUN_ALL_TESTS();
1821*33f37583SAndroid Build Coastguard Worker }
1822