blob: 89ca62b3bcb4758c12662cba5b7c0ef6e9b793cf [file] [log] [blame]
Andreas Gampe35e80932018-10-29 12:56:53 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jiyong Park715e23d2019-02-22 22:14:37 +090017#include <stdio.h>
Andreas Gampe35e80932018-10-29 12:56:53 -070018#include <algorithm>
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +000019#include <filesystem>
Andreas Gampea158e3d2018-12-10 13:46:30 -080020#include <fstream>
Jiyong Park715e23d2019-02-22 22:14:37 +090021#include <functional>
Andreas Gampea2bbbbe2018-12-21 15:05:48 -080022#include <memory>
Andreas Gampe35e80932018-10-29 12:56:53 -070023#include <string>
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +000024#include <unordered_set>
Andreas Gampe35e80932018-10-29 12:56:53 -070025#include <vector>
26
27#include <grp.h>
28#include <sys/stat.h>
29#include <sys/types.h>
30
31#include <android-base/file.h>
32#include <android-base/logging.h>
Andreas Gampe5ec47c52018-11-14 14:33:53 -080033#include <android-base/macros.h>
Jiyong Park715e23d2019-02-22 22:14:37 +090034#include <android-base/properties.h>
Andreas Gampec766c0a2018-12-06 15:51:21 -080035#include <android-base/scopeguard.h>
Andreas Gampe5ec47c52018-11-14 14:33:53 -080036#include <android-base/stringprintf.h>
Andreas Gampe35e80932018-10-29 12:56:53 -070037#include <android-base/strings.h>
Martijn Coenen44de00c2019-03-22 09:13:17 +010038#include <android/os/IVold.h>
Andreas Gampe35e80932018-10-29 12:56:53 -070039#include <binder/IServiceManager.h>
Nikita Ioffea82b0a82019-02-15 18:59:47 +000040#include <gmock/gmock.h>
Andreas Gampe35e80932018-10-29 12:56:53 -070041#include <gtest/gtest.h>
Andreas Gampeda5f5062019-03-26 12:19:13 -070042#include <libdm/dm.h>
Andreas Gampe35e80932018-10-29 12:56:53 -070043#include <selinux/selinux.h>
44
Dario Frenidded6c12018-11-19 16:02:26 +000045#include <android/apex/ApexInfo.h>
Andreas Gampe35e80932018-10-29 12:56:53 -070046#include <android/apex/IApexService.h>
Andreas Gampe35e80932018-10-29 12:56:53 -070047
Andreas Gampef35e1792019-04-01 15:58:03 -070048#include "apex_constants.h"
Andreas Gampec45bf322018-12-06 13:57:45 -080049#include "apex_file.h"
50#include "apex_manifest.h"
Andreas Gampe4510d492018-12-12 15:56:05 -080051#include "apexd_private.h"
Nikita Ioffe53c3dcd2019-02-08 17:39:00 +000052#include "apexd_session.h"
Nikita Ioffe61a9b532019-02-14 17:50:00 +000053#include "apexd_test_utils.h"
Andreas Gampee1a40392018-11-30 09:47:17 -080054#include "apexd_utils.h"
Andreas Gampe35e80932018-10-29 12:56:53 -070055#include "status_or.h"
56
Nikita Ioffe53c3dcd2019-02-08 17:39:00 +000057#include "session_state.pb.h"
58
59using apex::proto::SessionState;
60
Andreas Gampe35e80932018-10-29 12:56:53 -070061namespace android {
62namespace apex {
63
64using android::sp;
65using android::String16;
Nikita Ioffefa7b5da2019-04-10 12:15:53 +010066using android::apex::testing::ApexInfoEq;
Nikita Ioffe904e2d32019-02-19 01:57:13 +000067using android::apex::testing::CreateSessionInfo;
Nikita Ioffe61a9b532019-02-14 17:50:00 +000068using android::apex::testing::IsOk;
Nikita Ioffe904e2d32019-02-19 01:57:13 +000069using android::apex::testing::SessionInfoEq;
Andreas Gampe7f4ff352018-12-11 08:58:03 -080070using android::base::Join;
Nikita Ioffea82b0a82019-02-15 18:59:47 +000071using android::base::StringPrintf;
Nikita Ioffefa7b5da2019-04-10 12:15:53 +010072using ::testing::Contains;
Nikita Ioffe891723c2019-03-25 14:35:39 +000073using ::testing::EndsWith;
74using ::testing::HasSubstr;
75using ::testing::Not;
Nikita Ioffea82b0a82019-02-15 18:59:47 +000076using ::testing::UnorderedElementsAre;
Nikita Ioffe9ae986a2019-02-18 22:39:27 +000077using ::testing::UnorderedElementsAreArray;
Andreas Gampe35e80932018-10-29 12:56:53 -070078
Nikita Ioffe816a02b2019-02-16 16:49:45 +000079namespace fs = std::filesystem;
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +000080
Andreas Gampe35e80932018-10-29 12:56:53 -070081class ApexServiceTest : public ::testing::Test {
82 public:
83 ApexServiceTest() {
84 using android::IBinder;
85 using android::IServiceManager;
86
87 sp<IServiceManager> sm = android::defaultServiceManager();
88 sp<IBinder> binder = sm->getService(String16("apexservice"));
89 if (binder != nullptr) {
90 service_ = android::interface_cast<IApexService>(binder);
91 }
Martijn Coenen44de00c2019-03-22 09:13:17 +010092 binder = sm->getService(String16("vold"));
93 if (binder != nullptr) {
94 vold_service_ = android::interface_cast<android::os::IVold>(binder);
95 }
Andreas Gampe35e80932018-10-29 12:56:53 -070096 }
97
Andreas Gampe35e80932018-10-29 12:56:53 -070098 protected:
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +000099 void SetUp() override {
100 ASSERT_NE(nullptr, service_.get());
Martijn Coenen44de00c2019-03-22 09:13:17 +0100101 ASSERT_NE(nullptr, vold_service_.get());
102 android::binder::Status status =
103 vold_service_->supportsCheckpoint(&supports_fs_checkpointing_);
104 ASSERT_TRUE(IsOk(status));
Nikita Ioffe816a02b2019-02-16 16:49:45 +0000105 CleanUp();
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +0000106 }
107
Nikita Ioffe816a02b2019-02-16 16:49:45 +0000108 void TearDown() override { CleanUp(); }
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +0000109
Andreas Gampe35e80932018-10-29 12:56:53 -0700110 static std::string GetTestDataDir() {
Andreas Gampe0562bc52018-12-12 15:03:58 -0800111 return android::base::GetExecutableDirectory();
Andreas Gampe35e80932018-10-29 12:56:53 -0700112 }
Andreas Gampec45bf322018-12-06 13:57:45 -0800113 static std::string GetTestFile(const std::string& name) {
114 return GetTestDataDir() + "/" + name;
115 }
Andreas Gampe35e80932018-10-29 12:56:53 -0700116
117 static bool HaveSelinux() { return 1 == is_selinux_enabled(); }
118
119 static bool IsSelinuxEnforced() { return 0 != security_getenforce(); }
120
121 StatusOr<bool> IsActive(const std::string& name, int64_t version) {
Dario Frenidded6c12018-11-19 16:02:26 +0000122 std::vector<ApexInfo> list;
Andreas Gampe35e80932018-10-29 12:56:53 -0700123 android::binder::Status status = service_->getActivePackages(&list);
124 if (status.isOk()) {
Dario Frenidded6c12018-11-19 16:02:26 +0000125 for (const ApexInfo& p : list) {
126 if (p.packageName == name && p.versionCode == version) {
Andreas Gampe35e80932018-10-29 12:56:53 -0700127 return StatusOr<bool>(true);
128 }
129 }
130 return StatusOr<bool>(false);
131 }
Nikita Ioffec5536262019-03-29 17:01:58 +0000132 return StatusOr<bool>::MakeError(status.exceptionMessage().c_str());
Andreas Gampe35e80932018-10-29 12:56:53 -0700133 }
134
Gavin Corkery729905c2019-03-21 11:52:06 +0000135 StatusOr<std::vector<ApexInfo>> GetAllPackages() {
136 std::vector<ApexInfo> list;
137 android::binder::Status status = service_->getAllPackages(&list);
138 if (status.isOk()) {
139 return StatusOr<std::vector<ApexInfo>>(list);
140 }
141
142 return StatusOr<std::vector<ApexInfo>>::MakeError(
143 status.toString8().c_str());
144 }
145
Narayan Kamath5ea57782019-01-03 18:17:05 +0000146 StatusOr<std::vector<ApexInfo>> GetActivePackages() {
147 std::vector<ApexInfo> list;
148 android::binder::Status status = service_->getActivePackages(&list);
149 if (status.isOk()) {
150 return StatusOr<std::vector<ApexInfo>>(list);
151 }
152
153 return StatusOr<std::vector<ApexInfo>>::MakeError(
Nikita Ioffec5536262019-03-29 17:01:58 +0000154 status.exceptionMessage().c_str());
Narayan Kamath5ea57782019-01-03 18:17:05 +0000155 }
156
Gavin Corkery729905c2019-03-21 11:52:06 +0000157 StatusOr<std::vector<ApexInfo>> GetInactivePackages() {
158 std::vector<ApexInfo> list;
159 android::binder::Status status = service_->getAllPackages(&list);
160 list.erase(std::remove_if(
161 list.begin(), list.end(),
162 [](const ApexInfo& apexInfo) { return apexInfo.isActive; }),
163 list.end());
164 if (status.isOk()) {
165 return StatusOr<std::vector<ApexInfo>>(std::move(list));
166 }
167
168 return StatusOr<std::vector<ApexInfo>>::MakeError(
169 status.toString8().c_str());
170 }
171
Narayan Kamath5ea57782019-01-03 18:17:05 +0000172 StatusOr<ApexInfo> GetActivePackage(const std::string& name) {
173 ApexInfo package;
174 android::binder::Status status = service_->getActivePackage(name, &package);
175 if (status.isOk()) {
176 return StatusOr<ApexInfo>(package);
177 }
178
Nikita Ioffec5536262019-03-29 17:01:58 +0000179 return StatusOr<ApexInfo>::MakeError(status.exceptionMessage().c_str());
Narayan Kamath5ea57782019-01-03 18:17:05 +0000180 }
181
Gavin Corkery729905c2019-03-21 11:52:06 +0000182 std::string GetPackageString(const ApexInfo& p) {
183 return p.packageName + "@" + std::to_string(p.versionCode) +
184 " [path=" + p.packagePath + "]";
185 }
186
187 std::vector<std::string> GetPackagesStrings(
188 const std::vector<ApexInfo>& list) {
189 std::vector<std::string> ret;
Jooyung Hanac9fea62019-05-08 12:16:24 +0900190 ret.reserve(list.size());
Gavin Corkery729905c2019-03-21 11:52:06 +0000191 for (const ApexInfo& p : list) {
192 ret.push_back(GetPackageString(p));
193 }
194 return ret;
195 }
196
Andreas Gampe35e80932018-10-29 12:56:53 -0700197 std::vector<std::string> GetActivePackagesStrings() {
Dario Frenidded6c12018-11-19 16:02:26 +0000198 std::vector<ApexInfo> list;
Andreas Gampe35e80932018-10-29 12:56:53 -0700199 android::binder::Status status = service_->getActivePackages(&list);
200 if (status.isOk()) {
Dario Freni64255112019-02-18 22:13:38 +0000201 std::vector<std::string> ret(list.size());
Dario Frenidded6c12018-11-19 16:02:26 +0000202 for (const ApexInfo& p : list) {
Gavin Corkery729905c2019-03-21 11:52:06 +0000203 ret.push_back(GetPackageString(p));
Andreas Gampe35e80932018-10-29 12:56:53 -0700204 }
205 return ret;
206 }
207
208 std::vector<std::string> error;
209 error.push_back("ERROR");
210 return error;
211 }
212
Gavin Corkery729905c2019-03-21 11:52:06 +0000213 StatusOr<std::vector<ApexInfo>> GetFactoryPackages() {
214 std::vector<ApexInfo> list;
215 android::binder::Status status = service_->getAllPackages(&list);
216 list.erase(
217 std::remove_if(list.begin(), list.end(),
218 [](ApexInfo& apexInfo) { return !apexInfo.isFactory; }),
219 list.end());
220 if (status.isOk()) {
221 return StatusOr<std::vector<ApexInfo>>(std::move(list));
222 }
223
224 return StatusOr<std::vector<ApexInfo>>::MakeError(
225 status.toString8().c_str());
226 }
227
Andreas Gampe7f4ff352018-12-11 08:58:03 -0800228 static std::vector<std::string> ListDir(const std::string& path) {
229 std::vector<std::string> ret;
Mohammad Samiul Islam2d56f372019-03-27 17:07:57 +0000230 std::error_code ec;
231 if (!fs::is_directory(path, ec)) {
Andreas Gampe7f4ff352018-12-11 08:58:03 -0800232 return ret;
233 }
Jooyung Hanac9fea62019-05-08 12:16:24 +0900234 WalkDir(path, [&](const fs::directory_entry& entry) {
Andreas Gampe7f4ff352018-12-11 08:58:03 -0800235 std::string tmp;
Mohammad Samiul Islam2d56f372019-03-27 17:07:57 +0000236 switch (entry.symlink_status(ec).type()) {
237 case fs::file_type::directory:
Andreas Gampe7f4ff352018-12-11 08:58:03 -0800238 tmp = "[dir]";
239 break;
Mohammad Samiul Islam2d56f372019-03-27 17:07:57 +0000240 case fs::file_type::symlink:
Andreas Gampe7f4ff352018-12-11 08:58:03 -0800241 tmp = "[lnk]";
242 break;
Mohammad Samiul Islam2d56f372019-03-27 17:07:57 +0000243 case fs::file_type::regular:
Andreas Gampe7f4ff352018-12-11 08:58:03 -0800244 tmp = "[reg]";
245 break;
246 default:
247 tmp = "[other]";
Andreas Gampe7f4ff352018-12-11 08:58:03 -0800248 }
Jooyung Hanac9fea62019-05-08 12:16:24 +0900249 ret.push_back(tmp.append(entry.path().filename()));
250 });
Andreas Gampe7f4ff352018-12-11 08:58:03 -0800251 std::sort(ret.begin(), ret.end());
252 return ret;
253 }
254
Andreas Gampee1a40392018-11-30 09:47:17 -0800255 static std::string GetLogcat() {
256 // For simplicity, log to file and read it.
257 std::string file = GetTestFile("logcat.tmp.txt");
258 std::vector<std::string> args{
259 "/system/bin/logcat",
260 "-d",
261 "-f",
262 file,
263 };
264 std::string error_msg;
265 int res = ForkAndRun(args, &error_msg);
266 CHECK_EQ(0, res) << error_msg;
267
268 std::string data;
269 CHECK(android::base::ReadFileToString(file, &data));
270
271 unlink(file.c_str());
272
273 return data;
274 }
275
Andreas Gampe35e80932018-10-29 12:56:53 -0700276 struct PrepareTestApexForInstall {
Gavin Corkeryd12ea222019-02-27 11:26:16 +0000277 static constexpr const char* kTestDir = "/data/app-staging/apexservice_tmp";
Andreas Gampec45bf322018-12-06 13:57:45 -0800278
279 // This is given to the constructor.
Jooyung Hanac9fea62019-05-08 12:16:24 +0900280 std::string test_input; // Original test file.
Dario Freni56231b42019-01-04 11:58:17 +0000281 std::string selinux_label_input; // SELinux label to apply.
282 std::string test_dir_input;
Andreas Gampec45bf322018-12-06 13:57:45 -0800283
284 // This is derived from the input.
Dario Freni56231b42019-01-04 11:58:17 +0000285 std::string test_file; // Prepared path. Under test_dir_input.
Andreas Gampec45bf322018-12-06 13:57:45 -0800286 std::string test_installed_file; // Where apexd will store it.
287
288 std::string package; // APEX package name.
Dario Freni56231b42019-01-04 11:58:17 +0000289 uint64_t version; // APEX version
Andreas Gampec45bf322018-12-06 13:57:45 -0800290
Dario Freni56231b42019-01-04 11:58:17 +0000291 explicit PrepareTestApexForInstall(
292 const std::string& test,
293 const std::string& test_dir = std::string(kTestDir),
Nikita Ioffe936a9972019-02-13 02:11:21 +0000294 const std::string& selinux_label = "staging_data_file") {
Andreas Gampec45bf322018-12-06 13:57:45 -0800295 test_input = test;
Dario Freni56231b42019-01-04 11:58:17 +0000296 selinux_label_input = selinux_label;
297 test_dir_input = test_dir;
Andreas Gampec45bf322018-12-06 13:57:45 -0800298
Dario Freni56231b42019-01-04 11:58:17 +0000299 test_file = test_dir_input + "/" + android::base::Basename(test);
Andreas Gampec45bf322018-12-06 13:57:45 -0800300
Andreas Gampe0562bc52018-12-12 15:03:58 -0800301 package = ""; // Explicitly mark as not initialized.
302
Andreas Gampec45bf322018-12-06 13:57:45 -0800303 StatusOr<ApexFile> apex_file = ApexFile::Open(test);
Andreas Gampe0562bc52018-12-12 15:03:58 -0800304 if (!apex_file.Ok()) {
305 return;
306 }
Andreas Gampec45bf322018-12-06 13:57:45 -0800307
308 const ApexManifest& manifest = apex_file->GetManifest();
Abhijeet Kaur216e36c2019-01-04 10:15:01 +0000309 package = manifest.name();
310 version = manifest.version();
Andreas Gampec45bf322018-12-06 13:57:45 -0800311
Nikita Ioffea8453da2019-01-30 21:29:13 +0000312 test_installed_file = std::string(kActiveApexPackagesDataDir) + "/" +
313 package + "@" + std::to_string(version) + ".apex";
Andreas Gampec45bf322018-12-06 13:57:45 -0800314 }
Andreas Gampe35e80932018-10-29 12:56:53 -0700315
316 bool Prepare() {
Andreas Gampe0562bc52018-12-12 15:03:58 -0800317 if (package.empty()) {
318 // Failure in constructor. Redo work to get error message.
319 auto fail_fn = [&]() {
320 StatusOr<ApexFile> apex_file = ApexFile::Open(test_input);
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000321 ASSERT_FALSE(IsOk(apex_file));
Andreas Gampe0562bc52018-12-12 15:03:58 -0800322 ASSERT_TRUE(apex_file.Ok())
323 << test_input << " failed to load: " << apex_file.ErrorMessage();
324 };
325 fail_fn();
326 return false;
327 }
328
Dario Freni56231b42019-01-04 11:58:17 +0000329 auto prepare = [](const std::string& src, const std::string& trg,
330 const std::string& selinux_label) {
Andreas Gampec45bf322018-12-06 13:57:45 -0800331 ASSERT_EQ(0, access(src.c_str(), F_OK))
332 << src << ": " << strerror(errno);
333 const std::string trg_dir = android::base::Dirname(trg);
Andreas Gampea00c5452018-12-10 13:38:33 -0800334 if (0 != mkdir(trg_dir.c_str(), 0777)) {
335 int saved_errno = errno;
336 ASSERT_EQ(saved_errno, EEXIST) << trg << ":" << strerror(saved_errno);
337 }
Andreas Gampe35e80932018-10-29 12:56:53 -0700338
Andreas Gampea158e3d2018-12-10 13:46:30 -0800339 // Do not use a hardlink, even though it's the simplest solution.
340 // b/119569101.
341 {
342 std::ifstream src_stream(src, std::ios::binary);
343 ASSERT_TRUE(src_stream.good());
344 std::ofstream trg_stream(trg, std::ios::binary);
345 ASSERT_TRUE(trg_stream.good());
Andreas Gampe2f097cf2018-11-14 16:59:33 -0800346
Andreas Gampea158e3d2018-12-10 13:46:30 -0800347 trg_stream << src_stream.rdbuf();
Andreas Gampe2f097cf2018-11-14 16:59:33 -0800348 }
349
Andreas Gampec45bf322018-12-06 13:57:45 -0800350 ASSERT_EQ(0, chmod(trg.c_str(), 0666)) << strerror(errno);
Andreas Gampe35e80932018-10-29 12:56:53 -0700351 struct group* g = getgrnam("system");
352 ASSERT_NE(nullptr, g);
Andreas Gampec45bf322018-12-06 13:57:45 -0800353 ASSERT_EQ(0, chown(trg.c_str(), /* root uid */ 0, g->gr_gid))
Andreas Gampe35e80932018-10-29 12:56:53 -0700354 << strerror(errno);
Andreas Gampe2f097cf2018-11-14 16:59:33 -0800355
Dario Freni56231b42019-01-04 11:58:17 +0000356 int rc = setfilecon(
357 trg_dir.c_str(),
358 std::string("u:object_r:" + selinux_label + ":s0").c_str());
Andreas Gampec45bf322018-12-06 13:57:45 -0800359 ASSERT_TRUE(0 == rc || !HaveSelinux()) << strerror(errno);
Dario Freni56231b42019-01-04 11:58:17 +0000360 rc = setfilecon(
361 trg.c_str(),
362 std::string("u:object_r:" + selinux_label + ":s0").c_str());
Andreas Gampec45bf322018-12-06 13:57:45 -0800363 ASSERT_TRUE(0 == rc || !HaveSelinux()) << strerror(errno);
Andreas Gampe35e80932018-10-29 12:56:53 -0700364 };
Dario Freni56231b42019-01-04 11:58:17 +0000365 prepare(test_input, test_file, selinux_label_input);
Andreas Gampe35e80932018-10-29 12:56:53 -0700366 return !HasFatalFailure();
367 }
368
369 ~PrepareTestApexForInstall() {
Andreas Gampec45bf322018-12-06 13:57:45 -0800370 if (unlink(test_file.c_str()) != 0) {
371 PLOG(ERROR) << "Unable to unlink " << test_file;
Andreas Gampe35e80932018-10-29 12:56:53 -0700372 }
Dario Freni56231b42019-01-04 11:58:17 +0000373 if (rmdir(test_dir_input.c_str()) != 0) {
374 PLOG(ERROR) << "Unable to rmdir " << test_dir_input;
Andreas Gampe35e80932018-10-29 12:56:53 -0700375 }
Andreas Gampec45bf322018-12-06 13:57:45 -0800376
Andreas Gampe0562bc52018-12-12 15:03:58 -0800377 if (!package.empty()) {
378 // For cleanliness, also attempt to delete apexd's file.
379 // TODO: to the unstaging using APIs
380 if (unlink(test_installed_file.c_str()) != 0) {
381 PLOG(ERROR) << "Unable to unlink " << test_installed_file;
382 }
Andreas Gampec45bf322018-12-06 13:57:45 -0800383 }
Andreas Gampe35e80932018-10-29 12:56:53 -0700384 }
385 };
Andreas Gampe7f4ff352018-12-11 08:58:03 -0800386
387 std::string GetDebugStr(PrepareTestApexForInstall* installer) {
388 StringLog log;
389
390 if (installer != nullptr) {
391 log << "test_input=" << installer->test_input << " ";
392 log << "test_file=" << installer->test_file << " ";
393 log << "test_installed_file=" << installer->test_installed_file << " ";
394 log << "package=" << installer->package << " ";
395 log << "version=" << installer->version << " ";
396 }
397
398 log << "active=[" << Join(GetActivePackagesStrings(), ',') << "] ";
Nikita Ioffea8453da2019-01-30 21:29:13 +0000399 log << kActiveApexPackagesDataDir << "=["
400 << Join(ListDir(kActiveApexPackagesDataDir), ',') << "] ";
Andreas Gampe7f4ff352018-12-11 08:58:03 -0800401 log << kApexRoot << "=[" << Join(ListDir(kApexRoot), ',') << "]";
402
403 return log;
404 }
405
Andreas Gampe35e80932018-10-29 12:56:53 -0700406 sp<IApexService> service_;
Martijn Coenen44de00c2019-03-22 09:13:17 +0100407 sp<android::os::IVold> vold_service_;
408 bool supports_fs_checkpointing_;
Nikita Ioffe816a02b2019-02-16 16:49:45 +0000409
410 private:
411 void CleanUp() {
Jooyung Hanac9fea62019-05-08 12:16:24 +0900412 auto status = WalkDir(kApexDataDir, [](const fs::directory_entry& p) {
Nikita Ioffe816a02b2019-02-16 16:49:45 +0000413 std::error_code ec;
Jooyung Hanac9fea62019-05-08 12:16:24 +0900414 fs::file_status status = p.status(ec);
415 ASSERT_FALSE(ec) << "Failed to stat " << p.path() << " : "
416 << ec.message();
417 if (fs::is_directory(status)) {
Nikita Ioffe816a02b2019-02-16 16:49:45 +0000418 fs::remove_all(p.path(), ec);
Nikita Ioffe816a02b2019-02-16 16:49:45 +0000419 } else {
420 fs::remove(p.path(), ec);
Nikita Ioffe816a02b2019-02-16 16:49:45 +0000421 }
Jooyung Hanac9fea62019-05-08 12:16:24 +0900422 ASSERT_FALSE(ec) << "Failed to delete " << p.path() << " : "
423 << ec.message();
424 });
425 ASSERT_TRUE(IsOk(status));
Nikita Ioffe816a02b2019-02-16 16:49:45 +0000426 }
Andreas Gampe35e80932018-10-29 12:56:53 -0700427};
428
Andreas Gampea00c5452018-12-10 13:38:33 -0800429namespace {
430
431bool RegularFileExists(const std::string& path) {
432 struct stat buf;
433 if (0 != stat(path.c_str(), &buf)) {
434 return false;
435 }
436 return S_ISREG(buf.st_mode);
437}
438
439} // namespace
440
Andreas Gampe35e80932018-10-29 12:56:53 -0700441TEST_F(ApexServiceTest, HaveSelinux) {
442 // We want to test under selinux.
443 EXPECT_TRUE(HaveSelinux());
444}
445
Andreas Gampe1b6fa372018-11-05 09:47:28 -0800446// Skip for b/119032200.
447TEST_F(ApexServiceTest, DISABLED_EnforceSelinux) {
Andreas Gampe35e80932018-10-29 12:56:53 -0700448 // Crude cutout for virtual devices.
449#if !defined(__i386__) && !defined(__x86_64__)
450 constexpr bool kIsX86 = false;
451#else
452 constexpr bool kIsX86 = true;
453#endif
454 EXPECT_TRUE(IsSelinuxEnforced() || kIsX86);
455}
456
457TEST_F(ApexServiceTest, StageFailAccess) {
458 if (!IsSelinuxEnforced()) {
459 LOG(WARNING) << "Skipping InstallFailAccess because of selinux";
460 return;
461 }
462
463 // Use an extra copy, so that even if this test fails (incorrectly installs),
464 // we have the testdata file still around.
Andreas Gampe0562bc52018-12-12 15:03:58 -0800465 std::string orig_test_file = GetTestFile("apex.apexd_test.apex");
Andreas Gampe35e80932018-10-29 12:56:53 -0700466 std::string test_file = orig_test_file + ".2";
467 ASSERT_EQ(0, link(orig_test_file.c_str(), test_file.c_str()))
468 << strerror(errno);
469 struct Deleter {
470 std::string to_delete;
Chih-Hung Hsiehab73a442019-01-02 11:28:05 -0800471 explicit Deleter(const std::string& t) : to_delete(t) {}
Andreas Gampe35e80932018-10-29 12:56:53 -0700472 ~Deleter() {
473 if (unlink(to_delete.c_str()) != 0) {
474 PLOG(ERROR) << "Could not unlink " << to_delete;
475 }
476 }
477 };
478 Deleter del(test_file);
479
480 bool success;
481 android::binder::Status st = service_->stagePackage(test_file, &success);
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000482 ASSERT_FALSE(IsOk(st));
Nikita Ioffec5536262019-03-29 17:01:58 +0000483 std::string error = st.exceptionMessage().c_str();
Andreas Gampe35e80932018-10-29 12:56:53 -0700484 EXPECT_NE(std::string::npos, error.find("Failed to open package")) << error;
485 EXPECT_NE(std::string::npos, error.find("I/O error")) << error;
486}
487
Jiyong Park5e810232019-04-01 15:24:26 +0900488// TODO(jiyong): re-enable this test. This test is disabled because the build
489// system now always bundles the public key that was used to sign the APEX.
490// In debuggable build, the bundled public key is used as the last fallback.
491// As a result, the verification is always successful (and thus test fails).
492// In order to re-enable this test, we have to manually create an APEX
493// where public key is not bundled.
494#if 0
Andreas Gampecfb1ffe2018-12-26 15:23:53 -0800495TEST_F(ApexServiceTest, StageFailKey) {
496 PrepareTestApexForInstall installer(
497 GetTestFile("apex.apexd_test_no_inst_key.apex"));
498 if (!installer.Prepare()) {
499 return;
500 }
501 ASSERT_EQ(std::string("com.android.apex.test_package.no_inst_key"),
502 installer.package);
503
504 bool success;
505 android::binder::Status st =
506 service_->stagePackage(installer.test_file, &success);
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000507 ASSERT_FALSE(IsOk(st));
Jiyong Park997fcbf2018-12-27 16:07:49 +0900508
509 // May contain one of two errors.
Nikita Ioffec5536262019-03-29 17:01:58 +0000510 std::string error = st.exceptionMessage().c_str();
Jiyong Park997fcbf2018-12-27 16:07:49 +0900511
Andreas Gampecfb1ffe2018-12-26 15:23:53 -0800512 constexpr const char* kExpectedError1 = "Failed to get realpath of ";
Jiyong Park997fcbf2018-12-27 16:07:49 +0900513 const size_t pos1 = error.find(kExpectedError1);
Andreas Gampecfb1ffe2018-12-26 15:23:53 -0800514 constexpr const char* kExpectedError2 =
515 "/etc/security/apex/com.android.apex.test_package.no_inst_key";
Jiyong Park997fcbf2018-12-27 16:07:49 +0900516 const size_t pos2 = error.find(kExpectedError2);
517
518 constexpr const char* kExpectedError3 =
519 "Error verifying "
Gavin Corkeryd12ea222019-02-27 11:26:16 +0000520 "/data/app-staging/apexservice_tmp/apex.apexd_test_no_inst_key.apex: "
Jiyong Park997fcbf2018-12-27 16:07:49 +0900521 "couldn't verify public key: Failed to compare the bundled public key "
522 "with key";
523 const size_t pos3 = error.find(kExpectedError3);
524
525 const size_t npos = std::string::npos;
526 EXPECT_TRUE((pos1 != npos && pos2 != npos) || pos3 != npos) << error;
Andreas Gampecfb1ffe2018-12-26 15:23:53 -0800527}
Jiyong Park5e810232019-04-01 15:24:26 +0900528#endif
Andreas Gampecfb1ffe2018-12-26 15:23:53 -0800529
Andreas Gampe35e80932018-10-29 12:56:53 -0700530TEST_F(ApexServiceTest, StageSuccess) {
Andreas Gampe0562bc52018-12-12 15:03:58 -0800531 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"));
Andreas Gampe35e80932018-10-29 12:56:53 -0700532 if (!installer.Prepare()) {
533 return;
534 }
Andreas Gampe7f4ff352018-12-11 08:58:03 -0800535 ASSERT_EQ(std::string("com.android.apex.test_package"), installer.package);
Andreas Gampe35e80932018-10-29 12:56:53 -0700536
537 bool success;
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000538 ASSERT_TRUE(IsOk(service_->stagePackage(installer.test_file, &success)));
Andreas Gampe35e80932018-10-29 12:56:53 -0700539 ASSERT_TRUE(success);
Andreas Gampea00c5452018-12-10 13:38:33 -0800540 EXPECT_TRUE(RegularFileExists(installer.test_installed_file));
541}
542
Nikita Ioffebfebf652019-04-05 22:00:00 +0100543TEST_F(ApexServiceTest,
544 SubmitStagegSessionSuccessDoesNotLeakTempVerityDevices) {
Nikita Ioffe891723c2019-03-25 14:35:39 +0000545 using android::dm::DeviceMapper;
546
Nikita Ioffebfebf652019-04-05 22:00:00 +0100547 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
548 "/data/app-staging/session_1543",
549 "staging_data_file");
Nikita Ioffe891723c2019-03-25 14:35:39 +0000550 if (!installer.Prepare()) {
551 return;
552 }
553
Nikita Ioffebfebf652019-04-05 22:00:00 +0100554 ApexInfoList list;
Nikita Ioffe891723c2019-03-25 14:35:39 +0000555 bool success;
Nikita Ioffebfebf652019-04-05 22:00:00 +0100556 ASSERT_TRUE(IsOk(service_->submitStagedSession(1543, {}, &list, &success)));
Nikita Ioffe891723c2019-03-25 14:35:39 +0000557 ASSERT_TRUE(success);
558
559 std::vector<DeviceMapper::DmBlockDevice> devices;
560 DeviceMapper& dm = DeviceMapper::Instance();
561 ASSERT_TRUE(dm.GetAvailableDevices(&devices));
562
563 for (const auto& device : devices) {
564 ASSERT_THAT(device.name(), Not(EndsWith(".tmp")));
565 }
566}
567
Gavin Corkerya41373a2019-09-26 12:53:45 +0100568TEST_F(ApexServiceTest, SubmitStagedSessionStoresBuildFingerprint) {
569 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
570 "/data/app-staging/session_1547",
571 "staging_data_file");
572 if (!installer.Prepare()) {
573 return;
574 }
575 ApexInfoList list;
576 bool success;
577 ASSERT_TRUE(IsOk(service_->submitStagedSession(1547, {}, &list, &success)));
578
579 auto session = ApexSession::GetSession(1547);
580 ASSERT_FALSE(session->GetBuildFingerprint().empty());
581}
582
Nikita Ioffebfebf652019-04-05 22:00:00 +0100583TEST_F(ApexServiceTest, SubmitStagedSessionFailDoesNotLeakTempVerityDevices) {
Nikita Ioffe891723c2019-03-25 14:35:39 +0000584 using android::dm::DeviceMapper;
585
586 PrepareTestApexForInstall installer(
Nikita Ioffebfebf652019-04-05 22:00:00 +0100587 GetTestFile("apex.apexd_test_manifest_mismatch.apex"),
588 "/data/app-staging/session_239", "staging_data_file");
Nikita Ioffe891723c2019-03-25 14:35:39 +0000589 if (!installer.Prepare()) {
590 return;
591 }
592
Nikita Ioffebfebf652019-04-05 22:00:00 +0100593 ApexInfoList list;
Nikita Ioffe891723c2019-03-25 14:35:39 +0000594 bool success;
Nikita Ioffebfebf652019-04-05 22:00:00 +0100595 ASSERT_TRUE(IsOk(service_->submitStagedSession(239, {}, &list, &success)));
596 ASSERT_FALSE(success);
Nikita Ioffe891723c2019-03-25 14:35:39 +0000597
598 std::vector<DeviceMapper::DmBlockDevice> devices;
599 DeviceMapper& dm = DeviceMapper::Instance();
600 ASSERT_TRUE(dm.GetAvailableDevices(&devices));
601
602 for (const auto& device : devices) {
603 ASSERT_THAT(device.name(), Not(EndsWith(".tmp")));
604 }
605}
606
Nikita Ioffe6a280af2019-02-04 15:28:57 +0000607TEST_F(ApexServiceTest, StageSuccess_ClearsPreviouslyActivePackage) {
608 PrepareTestApexForInstall installer1(GetTestFile("apex.apexd_test_v2.apex"));
609 PrepareTestApexForInstall installer2(
610 GetTestFile("apex.apexd_test_different_app.apex"));
611 PrepareTestApexForInstall installer3(GetTestFile("apex.apexd_test.apex"));
612 auto install_fn = [&](PrepareTestApexForInstall& installer) {
613 if (!installer.Prepare()) {
614 return;
615 }
616 bool success;
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000617 ASSERT_TRUE(IsOk(service_->stagePackage(installer.test_file, &success)));
Nikita Ioffe6a280af2019-02-04 15:28:57 +0000618 ASSERT_TRUE(success);
619 EXPECT_TRUE(RegularFileExists(installer.test_installed_file));
620 };
621 install_fn(installer1);
622 install_fn(installer2);
623 // Simulating a rollback. After this call test_v2_apex_path should be removed.
624 install_fn(installer3);
625
626 EXPECT_FALSE(RegularFileExists(installer1.test_installed_file));
627 EXPECT_TRUE(RegularFileExists(installer2.test_installed_file));
628 EXPECT_TRUE(RegularFileExists(installer3.test_installed_file));
629}
630
Nikita Ioffea8365762019-03-18 23:59:03 +0000631TEST_F(ApexServiceTest, StageAlreadyStagedPackageSuccess) {
Nikita Ioffe8be420a2019-02-13 20:51:05 +0000632 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"));
633 if (!installer.Prepare()) {
634 return;
635 }
636 ASSERT_EQ(std::string("com.android.apex.test_package"), installer.package);
637
638 bool success = false;
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000639 ASSERT_TRUE(IsOk(service_->stagePackage(installer.test_file, &success)));
Nikita Ioffe8be420a2019-02-13 20:51:05 +0000640 ASSERT_TRUE(success);
641 ASSERT_TRUE(RegularFileExists(installer.test_installed_file));
642
643 success = false;
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000644 ASSERT_TRUE(IsOk(service_->stagePackage(installer.test_file, &success)));
Nikita Ioffe8be420a2019-02-13 20:51:05 +0000645 ASSERT_TRUE(success);
646 ASSERT_TRUE(RegularFileExists(installer.test_installed_file));
647}
648
Andreas Gampea00c5452018-12-10 13:38:33 -0800649TEST_F(ApexServiceTest, MultiStageSuccess) {
Andreas Gampe0562bc52018-12-12 15:03:58 -0800650 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"));
Andreas Gampea00c5452018-12-10 13:38:33 -0800651 if (!installer.Prepare()) {
652 return;
653 }
654 ASSERT_EQ(std::string("com.android.apex.test_package"), installer.package);
655
656 // TODO: Add second test. Right now, just use a separate version.
Andreas Gampe0562bc52018-12-12 15:03:58 -0800657 PrepareTestApexForInstall installer2(GetTestFile("apex.apexd_test_v2.apex"));
Andreas Gampea00c5452018-12-10 13:38:33 -0800658 if (!installer2.Prepare()) {
659 return;
660 }
661 ASSERT_EQ(std::string("com.android.apex.test_package"), installer2.package);
662
663 std::vector<std::string> packages;
664 packages.push_back(installer.test_file);
665 packages.push_back(installer2.test_file);
666
667 bool success;
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000668 ASSERT_TRUE(IsOk(service_->stagePackages(packages, &success)));
Andreas Gampea00c5452018-12-10 13:38:33 -0800669 ASSERT_TRUE(success);
670 EXPECT_TRUE(RegularFileExists(installer.test_installed_file));
671 EXPECT_TRUE(RegularFileExists(installer2.test_installed_file));
Andreas Gampe35e80932018-10-29 12:56:53 -0700672}
673
Andreas Gampea2bbbbe2018-12-21 15:05:48 -0800674template <typename NameProvider>
675class ApexServiceActivationTest : public ApexServiceTest {
676 public:
Nikita Ioffe891723c2019-03-25 14:35:39 +0000677 ApexServiceActivationTest() : stage_package(true) {}
678
Jooyung Hanac9fea62019-05-08 12:16:24 +0900679 explicit ApexServiceActivationTest(bool stage_package)
Nikita Ioffe891723c2019-03-25 14:35:39 +0000680 : stage_package(stage_package) {}
681
Andreas Gampea2bbbbe2018-12-21 15:05:48 -0800682 void SetUp() override {
683 ApexServiceTest::SetUp();
684 ASSERT_NE(nullptr, service_.get());
Andreas Gampe35e80932018-10-29 12:56:53 -0700685
Andreas Gampea2bbbbe2018-12-21 15:05:48 -0800686 installer_ = std::make_unique<PrepareTestApexForInstall>(
687 GetTestFile(NameProvider::GetTestName()));
688 if (!installer_->Prepare()) {
689 return;
690 }
691 ASSERT_EQ(NameProvider::GetPackageName(), installer_->package);
692
693 {
694 // Check package is not active.
695 StatusOr<bool> active =
696 IsActive(installer_->package, installer_->version);
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000697 ASSERT_TRUE(IsOk(active));
Andreas Gampea2bbbbe2018-12-21 15:05:48 -0800698 ASSERT_FALSE(*active);
699 }
700
Nikita Ioffe891723c2019-03-25 14:35:39 +0000701 if (stage_package) {
Andreas Gampea2bbbbe2018-12-21 15:05:48 -0800702 bool success;
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000703 ASSERT_TRUE(
704 IsOk(service_->stagePackage(installer_->test_file, &success)));
Andreas Gampea2bbbbe2018-12-21 15:05:48 -0800705 ASSERT_TRUE(success);
706 }
Andreas Gampe35e80932018-10-29 12:56:53 -0700707 }
708
Andreas Gampea2bbbbe2018-12-21 15:05:48 -0800709 void TearDown() override {
710 // Attempt to deactivate.
711 if (installer_ != nullptr) {
Nikita Ioffe891723c2019-03-25 14:35:39 +0000712 if (stage_package) {
713 service_->deactivatePackage(installer_->test_installed_file);
714 } else {
715 service_->deactivatePackage(installer_->test_file);
716 }
Andreas Gampea2bbbbe2018-12-21 15:05:48 -0800717 }
718
719 installer_.reset();
Nikita Ioffe816a02b2019-02-16 16:49:45 +0000720 // ApexServiceTest::TearDown will wipe out everything under /data/apex.
721 // Since some of that information is required for deactivePackage binder
722 // call, it's required to be called after deactivating package.
723 ApexServiceTest::TearDown();
Andreas Gampe35e80932018-10-29 12:56:53 -0700724 }
725
Andreas Gampea2bbbbe2018-12-21 15:05:48 -0800726 std::unique_ptr<PrepareTestApexForInstall> installer_;
Nikita Ioffe891723c2019-03-25 14:35:39 +0000727
728 private:
729 bool stage_package;
Andreas Gampea2bbbbe2018-12-21 15:05:48 -0800730};
731
732struct SuccessNameProvider {
733 static std::string GetTestName() { return "apex.apexd_test.apex"; }
734 static std::string GetPackageName() {
735 return "com.android.apex.test_package";
736 }
737};
738
Martijn Coenen329f1122019-02-28 16:10:08 +0100739struct ManifestMismatchNameProvider {
740 static std::string GetTestName() {
741 return "apex.apexd_test_manifest_mismatch.apex";
742 }
743 static std::string GetPackageName() {
744 return "com.android.apex.test_package";
745 }
746};
747
748class ApexServiceActivationManifestMismatchFailure
Nikita Ioffe891723c2019-03-25 14:35:39 +0000749 : public ApexServiceActivationTest<ManifestMismatchNameProvider> {
750 public:
751 ApexServiceActivationManifestMismatchFailure()
752 : ApexServiceActivationTest(false) {}
753};
Martijn Coenen329f1122019-02-28 16:10:08 +0100754
755TEST_F(ApexServiceActivationManifestMismatchFailure,
756 ActivateFailsWithManifestMismatch) {
Nikita Ioffe891723c2019-03-25 14:35:39 +0000757 android::binder::Status st = service_->activatePackage(installer_->test_file);
Martijn Coenen329f1122019-02-28 16:10:08 +0100758 ASSERT_FALSE(IsOk(st));
759
Nikita Ioffec5536262019-03-29 17:01:58 +0000760 std::string error = st.exceptionMessage().c_str();
Nikita Ioffe891723c2019-03-25 14:35:39 +0000761 ASSERT_THAT(
762 error,
763 HasSubstr(
764 "Manifest inside filesystem does not match manifest outside it"));
Martijn Coenen329f1122019-02-28 16:10:08 +0100765}
766
Andreas Gampea2bbbbe2018-12-21 15:05:48 -0800767class ApexServiceActivationSuccessTest
768 : public ApexServiceActivationTest<SuccessNameProvider> {};
769
770TEST_F(ApexServiceActivationSuccessTest, Activate) {
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000771 ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
772 << GetDebugStr(installer_.get());
Andreas Gampe35e80932018-10-29 12:56:53 -0700773
774 {
775 // Check package is active.
Andreas Gampea2bbbbe2018-12-21 15:05:48 -0800776 StatusOr<bool> active = IsActive(installer_->package, installer_->version);
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000777 ASSERT_TRUE(IsOk(active));
Andreas Gampe7f4ff352018-12-11 08:58:03 -0800778 ASSERT_TRUE(*active) << Join(GetActivePackagesStrings(), ',');
Andreas Gampe35e80932018-10-29 12:56:53 -0700779 }
780
781 {
782 // Check that the "latest" view exists.
Andreas Gampea2bbbbe2018-12-21 15:05:48 -0800783 std::string latest_path =
784 std::string(kApexRoot) + "/" + installer_->package;
Andreas Gampe35e80932018-10-29 12:56:53 -0700785 struct stat buf;
786 ASSERT_EQ(0, stat(latest_path.c_str(), &buf)) << strerror(errno);
787 // Check that it is a folder.
788 EXPECT_TRUE(S_ISDIR(buf.st_mode));
789
790 // Collect direct entries of a folder.
791 auto collect_entries_fn = [](const std::string& path) {
792 std::vector<std::string> ret;
Jooyung Hanac9fea62019-05-08 12:16:24 +0900793 WalkDir(path, [&](const fs::directory_entry& entry) {
Mohammad Samiul Islam2d56f372019-03-27 17:07:57 +0000794 if (!entry.is_directory()) {
Jooyung Hanac9fea62019-05-08 12:16:24 +0900795 return;
Andreas Gampe35e80932018-10-29 12:56:53 -0700796 }
Jooyung Hanac9fea62019-05-08 12:16:24 +0900797 ret.emplace_back(entry.path().filename());
798 });
Andreas Gampe35e80932018-10-29 12:56:53 -0700799 std::sort(ret.begin(), ret.end());
800 return ret;
801 };
802
Andreas Gampec45bf322018-12-06 13:57:45 -0800803 std::string versioned_path = std::string(kApexRoot) + "/" +
Andreas Gampea2bbbbe2018-12-21 15:05:48 -0800804 installer_->package + "@" +
805 std::to_string(installer_->version);
Andreas Gampec45bf322018-12-06 13:57:45 -0800806 std::vector<std::string> versioned_folder_entries =
807 collect_entries_fn(versioned_path);
Andreas Gampe35e80932018-10-29 12:56:53 -0700808 std::vector<std::string> latest_folder_entries =
809 collect_entries_fn(latest_path);
810
811 EXPECT_TRUE(versioned_folder_entries == latest_folder_entries)
Andreas Gampe7f4ff352018-12-11 08:58:03 -0800812 << "Versioned: " << Join(versioned_folder_entries, ',')
813 << " Latest: " << Join(latest_folder_entries, ',');
Andreas Gampe35e80932018-10-29 12:56:53 -0700814 }
Andreas Gampea2bbbbe2018-12-21 15:05:48 -0800815}
Andreas Gampe35e80932018-10-29 12:56:53 -0700816
Narayan Kamath5ea57782019-01-03 18:17:05 +0000817TEST_F(ApexServiceActivationSuccessTest, GetActivePackages) {
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000818 ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
819 << GetDebugStr(installer_.get());
Narayan Kamath5ea57782019-01-03 18:17:05 +0000820
821 StatusOr<std::vector<ApexInfo>> active = GetActivePackages();
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000822 ASSERT_TRUE(IsOk(active));
Narayan Kamath5ea57782019-01-03 18:17:05 +0000823 ApexInfo match;
824
Dario Freni64255112019-02-18 22:13:38 +0000825 for (const ApexInfo& info : *active) {
Narayan Kamath5ea57782019-01-03 18:17:05 +0000826 if (info.packageName == installer_->package) {
827 match = info;
828 break;
829 }
830 }
831
832 ASSERT_EQ(installer_->package, match.packageName);
833 ASSERT_EQ(installer_->version, static_cast<uint64_t>(match.versionCode));
834 ASSERT_EQ(installer_->test_installed_file, match.packagePath);
835}
836
837TEST_F(ApexServiceActivationSuccessTest, GetActivePackage) {
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000838 ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
839 << GetDebugStr(installer_.get());
Narayan Kamath5ea57782019-01-03 18:17:05 +0000840
841 StatusOr<ApexInfo> active = GetActivePackage(installer_->package);
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000842 ASSERT_TRUE(IsOk(active));
Narayan Kamath5ea57782019-01-03 18:17:05 +0000843
844 ASSERT_EQ(installer_->package, active->packageName);
845 ASSERT_EQ(installer_->version, static_cast<uint64_t>(active->versionCode));
846 ASSERT_EQ(installer_->test_installed_file, active->packagePath);
847}
848
Gavin Corkery729905c2019-03-21 11:52:06 +0000849TEST_F(ApexServiceTest, GetFactoryPackages) {
850 using ::android::base::StartsWith;
851 StatusOr<std::vector<ApexInfo>> factoryPackages = GetFactoryPackages();
852 ASSERT_TRUE(IsOk(factoryPackages));
853 ASSERT_TRUE(factoryPackages->size() > 0);
854
855 for (const ApexInfo& package : *factoryPackages) {
Nikita Ioffee44c58a2019-04-29 14:07:11 +0100856 ASSERT_TRUE(isPathForBuiltinApexes(package.packagePath));
Gavin Corkery729905c2019-03-21 11:52:06 +0000857 }
858}
859
860TEST_F(ApexServiceTest, NoPackagesAreBothActiveAndInactive) {
861 StatusOr<std::vector<ApexInfo>> activePackages = GetActivePackages();
862 ASSERT_TRUE(IsOk(activePackages));
863 ASSERT_TRUE(activePackages->size() > 0);
864 StatusOr<std::vector<ApexInfo>> inactivePackages = GetInactivePackages();
865 ASSERT_TRUE(IsOk(inactivePackages));
866 std::vector<std::string> activePackagesStrings =
867 GetPackagesStrings(*activePackages);
868 std::vector<std::string> inactivePackagesStrings =
869 GetPackagesStrings(*inactivePackages);
870 std::sort(activePackagesStrings.begin(), activePackagesStrings.end());
871 std::sort(inactivePackagesStrings.begin(), inactivePackagesStrings.end());
872 std::vector<std::string> intersection;
873 std::set_intersection(
874 activePackagesStrings.begin(), activePackagesStrings.end(),
875 inactivePackagesStrings.begin(), inactivePackagesStrings.end(),
876 std::back_inserter(intersection));
877 ASSERT_EQ(intersection.size(), 0UL);
878}
879
880TEST_F(ApexServiceTest, GetAllPackages) {
881 StatusOr<std::vector<ApexInfo>> allPackages = GetAllPackages();
882 ASSERT_TRUE(IsOk(allPackages));
883 ASSERT_TRUE(allPackages->size() > 0);
884 StatusOr<std::vector<ApexInfo>> activePackages = GetActivePackages();
885 std::vector<std::string> activeStrings = GetPackagesStrings(*activePackages);
886 StatusOr<std::vector<ApexInfo>> factoryPackages = GetFactoryPackages();
887 std::vector<std::string> factoryStrings =
888 GetPackagesStrings(*factoryPackages);
889 for (ApexInfo& apexInfo : *allPackages) {
890 std::string packageString = GetPackageString(apexInfo);
891 bool shouldBeActive = std::find(activeStrings.begin(), activeStrings.end(),
892 packageString) != activeStrings.end();
893 bool shouldBeFactory =
894 std::find(factoryStrings.begin(), factoryStrings.end(),
895 packageString) != factoryStrings.end();
896 ASSERT_EQ(shouldBeActive, apexInfo.isActive);
897 ASSERT_EQ(shouldBeFactory, apexInfo.isFactory);
898 }
899}
900
Nikita Ioffea8365762019-03-18 23:59:03 +0000901TEST_F(ApexServiceActivationSuccessTest, StageAlreadyActivePackageSameVersion) {
902 ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
903 << GetDebugStr(installer_.get());
904
905 bool success = false;
906 ASSERT_TRUE(IsOk(service_->stagePackage(installer_->test_file, &success)));
907 ASSERT_TRUE(success);
908}
909
Andreas Gampeda5f5062019-03-26 12:19:13 -0700910class ApexServiceDeactivationTest : public ApexServiceActivationSuccessTest {
911 public:
912 void SetUp() override {
913 ApexServiceActivationSuccessTest::SetUp();
914
915 ASSERT_TRUE(installer_ != nullptr);
916 }
917
918 void TearDown() override {
919 installer_.reset();
920 ApexServiceActivationSuccessTest::TearDown();
921 }
922
923 std::unique_ptr<PrepareTestApexForInstall> installer_;
924};
925
Nikita Ioffebfebf652019-04-05 22:00:00 +0100926TEST_F(ApexServiceActivationSuccessTest, DmDeviceTearDown) {
Andreas Gampeda5f5062019-03-26 12:19:13 -0700927 std::string package_id =
928 installer_->package + "@" + std::to_string(installer_->version);
929
930 auto find_fn = [](const std::string& name) {
931 auto& dm = dm::DeviceMapper::Instance();
932 std::vector<dm::DeviceMapper::DmBlockDevice> devices;
933 if (!dm.GetAvailableDevices(&devices)) {
934 return StatusOr<bool>::Fail("GetAvailableDevices failed");
935 }
936 for (const auto& device : devices) {
937 if (device.name() == name) {
938 return StatusOr<bool>(true);
939 }
940 }
941 return StatusOr<bool>(false);
942 };
943
944#define ASSERT_FIND(type) \
945 { \
946 StatusOr<bool> res = find_fn(package_id); \
947 ASSERT_TRUE(res.Ok()); \
948 ASSERT_##type(*res); \
949 }
950
951 ASSERT_FIND(FALSE);
952
953 ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
954 << GetDebugStr(installer_.get());
955
956 ASSERT_FIND(TRUE);
957
958 ASSERT_TRUE(
959 IsOk(service_->deactivatePackage(installer_->test_installed_file)));
960
961 ASSERT_FIND(FALSE);
962
963 installer_.reset(); // Skip TearDown deactivatePackage.
964}
965
Andreas Gampef4c7e7c2019-01-14 12:33:34 -0800966class ApexServicePrePostInstallTest : public ApexServiceTest {
967 public:
968 template <typename Fn>
969 void RunPrePost(Fn fn, const std::vector<std::string>& apex_names,
Andreas Gampe1144b182019-02-04 15:28:12 -0800970 const char* test_message, bool expect_success = true) {
Andreas Gampef4c7e7c2019-01-14 12:33:34 -0800971 // Using unique_ptr is just the easiest here.
972 using InstallerUPtr = std::unique_ptr<PrepareTestApexForInstall>;
973 std::vector<InstallerUPtr> installers;
974 std::vector<std::string> pkgs;
Andreas Gampee1a40392018-11-30 09:47:17 -0800975
Andreas Gampef4c7e7c2019-01-14 12:33:34 -0800976 for (const std::string& apex_name : apex_names) {
977 InstallerUPtr installer(
978 new PrepareTestApexForInstall(GetTestFile(apex_name)));
979 if (!installer->Prepare()) {
980 return;
981 }
982 pkgs.push_back(installer->test_file);
983 installers.emplace_back(std::move(installer));
984 }
985 android::binder::Status st = (service_.get()->*fn)(pkgs);
Andreas Gampe1144b182019-02-04 15:28:12 -0800986 if (expect_success) {
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000987 ASSERT_TRUE(IsOk(st));
Andreas Gampe1144b182019-02-04 15:28:12 -0800988 } else {
Nikita Ioffe61a9b532019-02-14 17:50:00 +0000989 ASSERT_FALSE(IsOk(st));
Andreas Gampe1144b182019-02-04 15:28:12 -0800990 }
Andreas Gampee1a40392018-11-30 09:47:17 -0800991
Andreas Gampe1144b182019-02-04 15:28:12 -0800992 if (test_message != nullptr) {
993 std::string logcat = GetLogcat();
994 EXPECT_NE(std::string::npos, logcat.find(test_message)) << logcat;
995 }
Andreas Gampee44b5792018-12-13 15:48:45 -0800996
Andreas Gampef4c7e7c2019-01-14 12:33:34 -0800997 // Ensure that the package is neither active nor mounted.
998 for (const InstallerUPtr& installer : installers) {
999 StatusOr<bool> active = IsActive(installer->package, installer->version);
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001000 ASSERT_TRUE(IsOk(active));
Andreas Gampef4c7e7c2019-01-14 12:33:34 -08001001 EXPECT_FALSE(*active);
1002 }
1003 for (const InstallerUPtr& installer : installers) {
1004 StatusOr<ApexFile> apex = ApexFile::Open(installer->test_input);
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001005 ASSERT_TRUE(IsOk(apex));
Andreas Gampef4c7e7c2019-01-14 12:33:34 -08001006 std::string path =
1007 apexd_private::GetPackageMountPoint(apex->GetManifest());
1008 std::string entry = std::string("[dir]").append(path);
1009 std::vector<std::string> slash_apex = ListDir(kApexRoot);
1010 auto it = std::find(slash_apex.begin(), slash_apex.end(), entry);
1011 EXPECT_TRUE(it == slash_apex.end()) << Join(slash_apex, ',');
1012 }
Andreas Gampee44b5792018-12-13 15:48:45 -08001013 }
Andreas Gampef4c7e7c2019-01-14 12:33:34 -08001014};
1015
1016TEST_F(ApexServicePrePostInstallTest, Preinstall) {
1017 RunPrePost(&IApexService::preinstallPackages,
1018 {"apex.apexd_test_preinstall.apex"}, "sh : PreInstall Test");
Andreas Gampee44b5792018-12-13 15:48:45 -08001019}
1020
Andreas Gampef4c7e7c2019-01-14 12:33:34 -08001021TEST_F(ApexServicePrePostInstallTest, MultiPreinstall) {
1022 constexpr const char* kLogcatText =
Andreas Gampee44b5792018-12-13 15:48:45 -08001023 "sh : /apex/com.android.apex.test_package/etc/sample_prebuilt_file";
Andreas Gampef4c7e7c2019-01-14 12:33:34 -08001024 RunPrePost(&IApexService::preinstallPackages,
1025 {"apex.apexd_test_preinstall.apex", "apex.apexd_test.apex"},
1026 kLogcatText);
1027}
Andreas Gampee1a40392018-11-30 09:47:17 -08001028
Andreas Gampe1144b182019-02-04 15:28:12 -08001029TEST_F(ApexServicePrePostInstallTest, PreinstallFail) {
1030 RunPrePost(&IApexService::preinstallPackages,
1031 {"apex.apexd_test_prepostinstall.fail.apex"},
1032 /* test_message= */ nullptr, /* expect_success= */ false);
1033}
1034
Andreas Gampef4c7e7c2019-01-14 12:33:34 -08001035TEST_F(ApexServicePrePostInstallTest, Postinstall) {
1036 RunPrePost(&IApexService::postinstallPackages,
1037 {"apex.apexd_test_postinstall.apex"},
1038 "sh : PostInstall Test");
1039}
1040
1041TEST_F(ApexServicePrePostInstallTest, MultiPostinstall) {
1042 constexpr const char* kLogcatText =
1043 "sh : /apex/com.android.apex.test_package/etc/sample_prebuilt_file";
1044 RunPrePost(&IApexService::postinstallPackages,
1045 {"apex.apexd_test_postinstall.apex", "apex.apexd_test.apex"},
1046 kLogcatText);
Andreas Gampee1a40392018-11-30 09:47:17 -08001047}
1048
Andreas Gampe1144b182019-02-04 15:28:12 -08001049TEST_F(ApexServicePrePostInstallTest, PostinstallFail) {
1050 RunPrePost(&IApexService::postinstallPackages,
1051 {"apex.apexd_test_prepostinstall.fail.apex"},
1052 /* test_message= */ nullptr, /* expect_success= */ false);
1053}
1054
Dario Freniab5b6c42019-01-15 11:53:57 +00001055TEST_F(ApexServiceTest, SubmitSingleSessionTestSuccess) {
Dario Freni56231b42019-01-04 11:58:17 +00001056 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
Gavin Corkeryd12ea222019-02-27 11:26:16 +00001057 "/data/app-staging/session_123",
Dario Freni56231b42019-01-04 11:58:17 +00001058 "staging_data_file");
1059 if (!installer.Prepare()) {
1060 FAIL() << GetDebugStr(&installer);
1061 }
1062
Dario Frenia6ad33e2019-01-09 14:35:43 +00001063 ApexInfoList list;
1064 bool ret_value;
Dario Freniab5b6c42019-01-15 11:53:57 +00001065 std::vector<int> empty_child_session_ids;
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001066 ASSERT_TRUE(IsOk(service_->submitStagedSession(123, empty_child_session_ids,
1067 &list, &ret_value)))
1068 << GetDebugStr(&installer);
Dario Frenia6ad33e2019-01-09 14:35:43 +00001069 EXPECT_TRUE(ret_value);
1070 EXPECT_EQ(1u, list.apexInfos.size());
Dario Freni56231b42019-01-04 11:58:17 +00001071 ApexInfo match;
Dario Freni64255112019-02-18 22:13:38 +00001072 for (const ApexInfo& info : list.apexInfos) {
Dario Freni56231b42019-01-04 11:58:17 +00001073 if (info.packageName == installer.package) {
1074 match = info;
1075 break;
1076 }
1077 }
1078
1079 ASSERT_EQ(installer.package, match.packageName);
1080 ASSERT_EQ(installer.version, static_cast<uint64_t>(match.versionCode));
1081 ASSERT_EQ(installer.test_file, match.packagePath);
Dario Frenid2437642019-01-11 14:35:23 +00001082
1083 ApexSessionInfo session;
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001084 ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(123, &session)))
1085 << GetDebugStr(&installer);
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001086 ApexSessionInfo expected = CreateSessionInfo(123);
1087 expected.isVerified = true;
1088 EXPECT_THAT(session, SessionInfoEq(expected));
Dario Frenif36c9622019-01-25 11:30:00 +00001089
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001090 ASSERT_TRUE(IsOk(service_->markStagedSessionReady(123, &ret_value)))
1091 << GetDebugStr(&installer);
Dario Frenif36c9622019-01-25 11:30:00 +00001092 ASSERT_TRUE(ret_value);
1093
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001094 ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(123, &session)))
1095 << GetDebugStr(&installer);
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001096 expected.isVerified = false;
1097 expected.isStaged = true;
1098 EXPECT_THAT(session, SessionInfoEq(expected));
Dario Frenif36c9622019-01-25 11:30:00 +00001099
1100 // Call markStagedSessionReady again. Should be a no-op.
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001101 ASSERT_TRUE(IsOk(service_->markStagedSessionReady(123, &ret_value)))
1102 << GetDebugStr(&installer);
Dario Frenif36c9622019-01-25 11:30:00 +00001103 ASSERT_TRUE(ret_value);
1104
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001105 ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(123, &session)))
1106 << GetDebugStr(&installer);
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001107 EXPECT_THAT(session, SessionInfoEq(expected));
Martijn Coenen4d206422019-01-31 15:58:55 +01001108
1109 // See if the session is reported with getSessions() as well
1110 std::vector<ApexSessionInfo> sessions;
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001111 ASSERT_TRUE(IsOk(service_->getSessions(&sessions)))
1112 << GetDebugStr(&installer);
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001113 ASSERT_THAT(sessions, UnorderedElementsAre(SessionInfoEq(expected)));
Dario Freni56231b42019-01-04 11:58:17 +00001114}
1115
Nikita Ioffe9bd28b92019-03-04 22:18:07 +00001116TEST_F(ApexServiceTest, SubmitSingleStagedSessionDeletesPreviousSessions) {
Nikita Ioffe53c3dcd2019-02-08 17:39:00 +00001117 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
Gavin Corkeryd12ea222019-02-27 11:26:16 +00001118 "/data/app-staging/session_239",
Nikita Ioffe53c3dcd2019-02-08 17:39:00 +00001119 "staging_data_file");
1120 if (!installer.Prepare()) {
1121 FAIL() << GetDebugStr(&installer);
1122 }
1123
1124 // First simulate existence of a bunch of sessions.
1125 auto session1 = ApexSession::CreateSession(37);
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001126 ASSERT_TRUE(IsOk(session1));
Nikita Ioffe53c3dcd2019-02-08 17:39:00 +00001127 auto session2 = ApexSession::CreateSession(57);
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001128 ASSERT_TRUE(IsOk(session2));
Nikita Ioffe53c3dcd2019-02-08 17:39:00 +00001129 auto session3 = ApexSession::CreateSession(73);
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001130 ASSERT_TRUE(IsOk(session3));
1131 ASSERT_TRUE(IsOk(session1->UpdateStateAndCommit(SessionState::VERIFIED)));
1132 ASSERT_TRUE(IsOk(session2->UpdateStateAndCommit(SessionState::STAGED)));
Nikita Ioffe463d4e82019-02-10 18:46:20 +00001133 ASSERT_TRUE(IsOk(session3->UpdateStateAndCommit(SessionState::SUCCESS)));
Nikita Ioffe53c3dcd2019-02-08 17:39:00 +00001134
1135 std::vector<ApexSessionInfo> sessions;
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001136 ASSERT_TRUE(IsOk(service_->getSessions(&sessions)));
Nikita Ioffe53c3dcd2019-02-08 17:39:00 +00001137
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001138 ApexSessionInfo expected_session1 = CreateSessionInfo(37);
Nikita Ioffe53c3dcd2019-02-08 17:39:00 +00001139 expected_session1.isVerified = true;
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001140 ApexSessionInfo expected_session2 = CreateSessionInfo(57);
Nikita Ioffe53c3dcd2019-02-08 17:39:00 +00001141 expected_session2.isStaged = true;
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001142 ApexSessionInfo expected_session3 = CreateSessionInfo(73);
Nikita Ioffe463d4e82019-02-10 18:46:20 +00001143 expected_session3.isSuccess = true;
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001144 ASSERT_THAT(sessions, UnorderedElementsAre(SessionInfoEq(expected_session1),
1145 SessionInfoEq(expected_session2),
1146 SessionInfoEq(expected_session3)));
Nikita Ioffe53c3dcd2019-02-08 17:39:00 +00001147
1148 ApexInfoList list;
1149 bool ret_value;
1150 std::vector<int> empty_child_session_ids;
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001151 ASSERT_TRUE(IsOk(service_->submitStagedSession(239, empty_child_session_ids,
1152 &list, &ret_value)));
Nikita Ioffe53c3dcd2019-02-08 17:39:00 +00001153 EXPECT_TRUE(ret_value);
1154
1155 sessions.clear();
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001156 ASSERT_TRUE(IsOk(service_->getSessions(&sessions)));
Nikita Ioffe53c3dcd2019-02-08 17:39:00 +00001157
Nikita Ioffe9bd28b92019-03-04 22:18:07 +00001158 ApexSessionInfo new_session = CreateSessionInfo(239);
1159 new_session.isVerified = true;
1160 ASSERT_THAT(sessions, UnorderedElementsAre(SessionInfoEq(new_session)));
Nikita Ioffe53c3dcd2019-02-08 17:39:00 +00001161}
1162
Jiyong Park5e810232019-04-01 15:24:26 +09001163// TODO(jiyong): re-enable this test. This test is disabled because the build
1164// system now always bundles the public key that was used to sign the APEX.
1165// In debuggable build, the bundled public key is used as the last fallback.
1166// As a result, the verification is always successful (and thus test fails).
1167// In order to re-enable this test, we have to manually create an APEX
1168// where public key is not bundled.
1169#if 0
Dario Freniab5b6c42019-01-15 11:53:57 +00001170TEST_F(ApexServiceTest, SubmitSingleSessionTestFail) {
Dario Freni56231b42019-01-04 11:58:17 +00001171 PrepareTestApexForInstall installer(
1172 GetTestFile("apex.apexd_test_no_inst_key.apex"),
Gavin Corkeryd12ea222019-02-27 11:26:16 +00001173 "/data/app-staging/session_456", "staging_data_file");
Dario Freni56231b42019-01-04 11:58:17 +00001174 if (!installer.Prepare()) {
1175 FAIL() << GetDebugStr(&installer);
1176 }
1177
Dario Frenia6ad33e2019-01-09 14:35:43 +00001178 ApexInfoList list;
1179 bool ret_value;
Dario Freniab5b6c42019-01-15 11:53:57 +00001180 std::vector<int> empty_child_session_ids;
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001181 ASSERT_TRUE(IsOk(service_->submitStagedSession(456, empty_child_session_ids,
1182 &list, &ret_value)))
1183 << GetDebugStr(&installer);
Dario Frenia6ad33e2019-01-09 14:35:43 +00001184 EXPECT_FALSE(ret_value);
Dario Frenid2437642019-01-11 14:35:23 +00001185
1186 ApexSessionInfo session;
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001187 ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(456, &session)))
1188 << GetDebugStr(&installer);
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001189 ApexSessionInfo expected = CreateSessionInfo(-1);
1190 expected.isUnknown = true;
1191 EXPECT_THAT(session, SessionInfoEq(expected));
Dario Freni56231b42019-01-04 11:58:17 +00001192}
Jiyong Park5e810232019-04-01 15:24:26 +09001193#endif
Dario Freni56231b42019-01-04 11:58:17 +00001194
Dario Freni6dd4dd62019-01-18 12:45:44 +00001195TEST_F(ApexServiceTest, SubmitMultiSessionTestSuccess) {
1196 // Parent session id: 10
1197 // Children session ids: 20 30
1198 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
Gavin Corkeryd12ea222019-02-27 11:26:16 +00001199 "/data/app-staging/session_20",
Dario Freni6dd4dd62019-01-18 12:45:44 +00001200 "staging_data_file");
1201 PrepareTestApexForInstall installer2(
1202 GetTestFile("apex.apexd_test_different_app.apex"),
Gavin Corkeryd12ea222019-02-27 11:26:16 +00001203 "/data/app-staging/session_30", "staging_data_file");
Dario Freni6dd4dd62019-01-18 12:45:44 +00001204 if (!installer.Prepare() || !installer2.Prepare()) {
1205 FAIL() << GetDebugStr(&installer) << GetDebugStr(&installer2);
1206 }
1207
1208 ApexInfoList list;
1209 bool ret_value;
1210 std::vector<int> child_session_ids = {20, 30};
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001211 ASSERT_TRUE(IsOk(
1212 service_->submitStagedSession(10, child_session_ids, &list, &ret_value)))
1213 << GetDebugStr(&installer);
Dario Freni6dd4dd62019-01-18 12:45:44 +00001214 ASSERT_TRUE(ret_value);
1215 EXPECT_EQ(2u, list.apexInfos.size());
1216 ApexInfo match;
1217 bool package1_found = false;
1218 bool package2_found = false;
Dario Freni64255112019-02-18 22:13:38 +00001219 for (const ApexInfo& info : list.apexInfos) {
Dario Freni6dd4dd62019-01-18 12:45:44 +00001220 if (info.packageName == installer.package) {
1221 ASSERT_EQ(installer.package, info.packageName);
1222 ASSERT_EQ(installer.version, static_cast<uint64_t>(info.versionCode));
1223 ASSERT_EQ(installer.test_file, info.packagePath);
1224 package1_found = true;
1225 } else if (info.packageName == installer2.package) {
1226 ASSERT_EQ(installer2.package, info.packageName);
1227 ASSERT_EQ(installer2.version, static_cast<uint64_t>(info.versionCode));
1228 ASSERT_EQ(installer2.test_file, info.packagePath);
1229 package2_found = true;
1230 } else {
1231 FAIL() << "Unexpected package found " << info.packageName
1232 << GetDebugStr(&installer) << GetDebugStr(&installer2);
1233 }
1234 }
1235 ASSERT_TRUE(package1_found);
1236 ASSERT_TRUE(package2_found);
1237
1238 ApexSessionInfo session;
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001239 ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(10, &session)))
1240 << GetDebugStr(&installer);
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001241 ApexSessionInfo expected = CreateSessionInfo(10);
1242 expected.isVerified = true;
1243 ASSERT_THAT(session, SessionInfoEq(expected));
Dario Frenif36c9622019-01-25 11:30:00 +00001244
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001245 ASSERT_TRUE(IsOk(service_->markStagedSessionReady(10, &ret_value)))
1246 << GetDebugStr(&installer);
Dario Frenif36c9622019-01-25 11:30:00 +00001247 ASSERT_TRUE(ret_value);
1248
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001249 ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(10, &session)))
1250 << GetDebugStr(&installer);
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001251 expected.isVerified = false;
1252 expected.isStaged = true;
1253 ASSERT_THAT(session, SessionInfoEq(expected));
Dario Freni6dd4dd62019-01-18 12:45:44 +00001254}
1255
Jiyong Park5e810232019-04-01 15:24:26 +09001256// TODO(jiyong): re-enable this test. This test is disabled because the build
1257// system now always bundles the public key that was used to sign the APEX.
1258// In debuggable build, the bundled public key is used as the last fallback.
1259// As a result, the verification is always successful (and thus test fails).
1260// In order to re-enable this test, we have to manually create an APEX
1261// where public key is not bundled.
1262#if 0
Dario Freni6dd4dd62019-01-18 12:45:44 +00001263TEST_F(ApexServiceTest, SubmitMultiSessionTestFail) {
1264 // Parent session id: 11
1265 // Children session ids: 21 31
1266 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
Gavin Corkeryd12ea222019-02-27 11:26:16 +00001267 "/data/app-staging/session_21",
Dario Freni6dd4dd62019-01-18 12:45:44 +00001268 "staging_data_file");
1269 PrepareTestApexForInstall installer2(
1270 GetTestFile("apex.apexd_test_no_inst_key.apex"),
Gavin Corkeryd12ea222019-02-27 11:26:16 +00001271 "/data/app-staging/session_31", "staging_data_file");
Dario Freni6dd4dd62019-01-18 12:45:44 +00001272 if (!installer.Prepare() || !installer2.Prepare()) {
1273 FAIL() << GetDebugStr(&installer) << GetDebugStr(&installer2);
1274 }
1275 ApexInfoList list;
1276 bool ret_value;
1277 std::vector<int> child_session_ids = {21, 31};
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001278 ASSERT_TRUE(IsOk(
1279 service_->submitStagedSession(11, child_session_ids, &list, &ret_value)))
1280 << GetDebugStr(&installer);
Dario Freni6dd4dd62019-01-18 12:45:44 +00001281 ASSERT_FALSE(ret_value);
1282}
Jiyong Park5e810232019-04-01 15:24:26 +09001283#endif
Dario Freni6dd4dd62019-01-18 12:45:44 +00001284
Dario Frenif36c9622019-01-25 11:30:00 +00001285TEST_F(ApexServiceTest, MarkStagedSessionReadyFail) {
1286 // We should fail if we ask information about a session we don't know.
1287 bool ret_value;
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001288 ASSERT_TRUE(IsOk(service_->markStagedSessionReady(666, &ret_value)));
Dario Frenif36c9622019-01-25 11:30:00 +00001289 ASSERT_FALSE(ret_value);
1290
1291 ApexSessionInfo session;
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001292 ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(666, &session)));
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001293 ApexSessionInfo expected = CreateSessionInfo(-1);
1294 expected.isUnknown = true;
1295 ASSERT_THAT(session, SessionInfoEq(expected));
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +00001296}
1297
1298TEST_F(ApexServiceTest, MarkStagedSessionSuccessfulFailsNoSession) {
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001299 ASSERT_FALSE(IsOk(service_->markStagedSessionSuccessful(37)));
1300
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +00001301 ApexSessionInfo session_info;
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001302 ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(37, &session_info)));
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001303 ApexSessionInfo expected = CreateSessionInfo(-1);
1304 expected.isUnknown = true;
1305 ASSERT_THAT(session_info, SessionInfoEq(expected));
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +00001306}
1307
1308TEST_F(ApexServiceTest, MarkStagedSessionSuccessfulFailsSessionInWrongState) {
1309 auto session = ApexSession::CreateSession(73);
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001310 ASSERT_TRUE(IsOk(session));
1311 ASSERT_TRUE(
1312 IsOk(session->UpdateStateAndCommit(::apex::proto::SessionState::STAGED)));
1313
1314 ASSERT_FALSE(IsOk(service_->markStagedSessionSuccessful(73)));
1315
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +00001316 ApexSessionInfo session_info;
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001317 ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(73, &session_info)));
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001318 ApexSessionInfo expected = CreateSessionInfo(73);
1319 expected.isStaged = true;
1320 ASSERT_THAT(session_info, SessionInfoEq(expected));
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +00001321}
1322
1323TEST_F(ApexServiceTest, MarkStagedSessionSuccessfulActivatedSession) {
1324 auto session = ApexSession::CreateSession(239);
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001325 ASSERT_TRUE(IsOk(session));
1326 ASSERT_TRUE(IsOk(
1327 session->UpdateStateAndCommit(::apex::proto::SessionState::ACTIVATED)));
1328
1329 ASSERT_TRUE(IsOk(service_->markStagedSessionSuccessful(239)));
1330
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +00001331 ApexSessionInfo session_info;
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001332 ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(239, &session_info)));
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001333 ApexSessionInfo expected = CreateSessionInfo(239);
1334 expected.isSuccess = true;
1335 ASSERT_THAT(session_info, SessionInfoEq(expected));
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +00001336}
1337
1338TEST_F(ApexServiceTest, MarkStagedSessionSuccessfulNoOp) {
1339 auto session = ApexSession::CreateSession(1543);
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001340 ASSERT_TRUE(IsOk(session));
1341 ASSERT_TRUE(IsOk(
1342 session->UpdateStateAndCommit(::apex::proto::SessionState::SUCCESS)));
1343
1344 ASSERT_TRUE(IsOk(service_->markStagedSessionSuccessful(1543)));
1345
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +00001346 ApexSessionInfo session_info;
Nikita Ioffe61a9b532019-02-14 17:50:00 +00001347 ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(1543, &session_info)));
Nikita Ioffe904e2d32019-02-19 01:57:13 +00001348 ApexSessionInfo expected = CreateSessionInfo(1543);
1349 expected.isSuccess = true;
1350 ASSERT_THAT(session_info, SessionInfoEq(expected));
Dario Frenif36c9622019-01-25 11:30:00 +00001351}
1352
Nikita Ioffe463d4e82019-02-10 18:46:20 +00001353TEST_F(ApexServiceTest, AbortActiveSessionNoSessions) {
1354 // First ensure there are no sessions.
1355 std::vector<ApexSessionInfo> sessions;
1356 ASSERT_TRUE(IsOk(service_->getSessions(&sessions)));
1357 ASSERT_EQ(0u, sessions.size());
1358 ASSERT_TRUE(IsOk(service_->abortActiveSession()));
1359}
1360
1361TEST_F(ApexServiceTest, AbortActiveSession) {
1362 auto session = ApexSession::CreateSession(239);
1363 session->UpdateStateAndCommit(SessionState::VERIFIED);
1364
1365 std::vector<ApexSessionInfo> sessions;
1366 ASSERT_TRUE(IsOk(service_->getSessions(&sessions)));
1367 ASSERT_EQ(1u, sessions.size());
1368
1369 ASSERT_TRUE(IsOk(service_->abortActiveSession()));
1370
1371 sessions.clear();
1372 ASSERT_TRUE(IsOk(service_->getSessions(&sessions)));
1373 ASSERT_EQ(0u, sessions.size());
1374}
1375
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001376TEST_F(ApexServiceTest, BackupActivePackages) {
Martijn Coenen44de00c2019-03-22 09:13:17 +01001377 if (supports_fs_checkpointing_) {
Nikita Ioffe6f87d542019-04-09 13:09:26 +01001378 GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
Martijn Coenen44de00c2019-03-22 09:13:17 +01001379 }
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001380 PrepareTestApexForInstall installer1(GetTestFile("apex.apexd_test.apex"));
1381 PrepareTestApexForInstall installer2(
1382 GetTestFile("apex.apexd_test_different_app.apex"));
1383 PrepareTestApexForInstall installer3(GetTestFile("apex.apexd_test_v2.apex"),
Gavin Corkeryd12ea222019-02-27 11:26:16 +00001384 "/data/app-staging/session_23",
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001385 "staging_data_file");
1386
1387 if (!installer1.Prepare() || !installer2.Prepare() || !installer3.Prepare()) {
1388 return;
1389 }
1390
1391 // Activate some packages, in order to backup them later.
1392 bool ret = false;
1393 std::vector<std::string> pkgs = {installer1.test_file, installer2.test_file};
1394 ASSERT_TRUE(IsOk(service_->stagePackages(pkgs, &ret)));
1395 ASSERT_TRUE(ret);
1396
1397 // Make sure that /data/apex/active has activated packages.
Mohammad Samiul Islamd428a182019-03-19 14:36:24 +00001398 auto active_pkgs =
1399 ReadDir(kActiveApexPackagesDataDir, [](auto _) { return true; });
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001400 ASSERT_TRUE(IsOk(active_pkgs));
1401 ASSERT_THAT(*active_pkgs,
1402 UnorderedElementsAre(installer1.test_installed_file,
1403 installer2.test_installed_file));
1404
1405 ApexInfoList list;
1406 std::vector<int> empty_child_session_ids;
1407 ASSERT_TRUE(IsOk(
1408 service_->submitStagedSession(23, empty_child_session_ids, &list, &ret)));
1409 ASSERT_TRUE(ret);
1410
Mohammad Samiul Islamd428a182019-03-19 14:36:24 +00001411 auto backups = ReadDir(kApexBackupDir, [](auto _) { return true; });
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001412 ASSERT_TRUE(IsOk(backups));
1413 auto backup1 =
1414 StringPrintf("%s/com.android.apex.test_package@1.apex", kApexBackupDir);
1415 auto backup2 =
1416 StringPrintf("%s/com.android.apex.test_package_2@1.apex", kApexBackupDir);
1417 ASSERT_THAT(*backups, UnorderedElementsAre(backup1, backup2));
1418}
1419
1420TEST_F(ApexServiceTest, BackupActivePackagesClearsPreviousBackup) {
Martijn Coenen44de00c2019-03-22 09:13:17 +01001421 if (supports_fs_checkpointing_) {
Nikita Ioffe6f87d542019-04-09 13:09:26 +01001422 GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
Martijn Coenen44de00c2019-03-22 09:13:17 +01001423 }
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001424 PrepareTestApexForInstall installer1(GetTestFile("apex.apexd_test.apex"));
1425 PrepareTestApexForInstall installer2(
1426 GetTestFile("apex.apexd_test_different_app.apex"));
1427 PrepareTestApexForInstall installer3(GetTestFile("apex.apexd_test_v2.apex"),
Gavin Corkeryd12ea222019-02-27 11:26:16 +00001428 "/data/app-staging/session_43",
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001429 "staging_data_file");
1430
1431 if (!installer1.Prepare() || !installer2.Prepare() || !installer3.Prepare()) {
1432 return;
1433 }
1434
1435 // Make sure /data/apex/backups exists.
1436 ASSERT_TRUE(IsOk(createDirIfNeeded(std::string(kApexBackupDir), 0700)));
1437 // Create some bogus files in /data/apex/backups.
1438 std::ofstream old_backup(StringPrintf("%s/file1", kApexBackupDir));
1439 ASSERT_TRUE(old_backup.good());
1440 old_backup.close();
1441
1442 bool ret = false;
1443 std::vector<std::string> pkgs = {installer1.test_file, installer2.test_file};
1444 ASSERT_TRUE(IsOk(service_->stagePackages(pkgs, &ret)));
1445 ASSERT_TRUE(ret);
1446
1447 // Make sure that /data/apex/active has activated packages.
Mohammad Samiul Islamd428a182019-03-19 14:36:24 +00001448 auto active_pkgs =
1449 ReadDir(kActiveApexPackagesDataDir, [](auto _) { return true; });
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001450 ASSERT_TRUE(IsOk(active_pkgs));
1451 ASSERT_THAT(*active_pkgs,
1452 UnorderedElementsAre(installer1.test_installed_file,
1453 installer2.test_installed_file));
1454
1455 ApexInfoList list;
1456 std::vector<int> empty_child_session_ids;
1457 ASSERT_TRUE(IsOk(
1458 service_->submitStagedSession(43, empty_child_session_ids, &list, &ret)));
1459 ASSERT_TRUE(ret);
1460
Mohammad Samiul Islamd428a182019-03-19 14:36:24 +00001461 auto backups = ReadDir(kApexBackupDir, [](auto _) { return true; });
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001462 ASSERT_TRUE(IsOk(backups));
1463 auto backup1 =
1464 StringPrintf("%s/com.android.apex.test_package@1.apex", kApexBackupDir);
1465 auto backup2 =
1466 StringPrintf("%s/com.android.apex.test_package_2@1.apex", kApexBackupDir);
1467 ASSERT_THAT(*backups, UnorderedElementsAre(backup1, backup2));
1468}
1469
1470TEST_F(ApexServiceTest, BackupActivePackagesZeroActivePackages) {
Martijn Coenen44de00c2019-03-22 09:13:17 +01001471 if (supports_fs_checkpointing_) {
Nikita Ioffe6f87d542019-04-09 13:09:26 +01001472 GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
Martijn Coenen44de00c2019-03-22 09:13:17 +01001473 }
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001474 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"),
Gavin Corkeryd12ea222019-02-27 11:26:16 +00001475 "/data/app-staging/session_41",
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001476 "staging_data_file");
1477
1478 if (!installer.Prepare()) {
1479 return;
1480 }
1481
1482 // Make sure that /data/apex/active exists and is empty
1483 ASSERT_TRUE(
1484 IsOk(createDirIfNeeded(std::string(kActiveApexPackagesDataDir), 0750)));
Mohammad Samiul Islamd428a182019-03-19 14:36:24 +00001485 auto active_pkgs =
1486 ReadDir(kActiveApexPackagesDataDir, [](auto _) { return true; });
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001487 ASSERT_TRUE(IsOk(active_pkgs));
1488 ASSERT_EQ(0u, active_pkgs->size());
1489
1490 ApexInfoList list;
1491 std::vector<int> empty_child_session_ids;
1492 bool ret = false;
1493 ASSERT_TRUE(IsOk(
1494 service_->submitStagedSession(41, empty_child_session_ids, &list, &ret)));
1495 ASSERT_TRUE(ret);
1496
Mohammad Samiul Islamd428a182019-03-19 14:36:24 +00001497 auto backups = ReadDir(kApexBackupDir, [](auto _) { return true; });
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001498 ASSERT_TRUE(IsOk(backups));
1499 ASSERT_EQ(0u, backups->size());
1500}
1501
1502TEST_F(ApexServiceTest, ActivePackagesFolderDoesNotExist) {
1503 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"),
Gavin Corkeryd12ea222019-02-27 11:26:16 +00001504 "/data/app-staging/session_41",
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001505 "staging_data_file");
1506
1507 if (!installer.Prepare()) {
1508 return;
1509 }
1510
1511 // Make sure that /data/apex/active does not exist
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001512 std::error_code ec;
1513 fs::remove_all(fs::path(kActiveApexPackagesDataDir), ec);
1514 ASSERT_FALSE(ec) << "Failed to delete " << kActiveApexPackagesDataDir;
1515
1516 ApexInfoList list;
1517 std::vector<int> empty_child_session_ids;
1518 bool ret = false;
1519 ASSERT_TRUE(IsOk(
1520 service_->submitStagedSession(41, empty_child_session_ids, &list, &ret)));
1521 ASSERT_TRUE(ret);
1522
Martijn Coenen44de00c2019-03-22 09:13:17 +01001523 if (!supports_fs_checkpointing_) {
Mohammad Samiul Islamd428a182019-03-19 14:36:24 +00001524 auto backups = ReadDir(kApexBackupDir, [](auto _) { return true; });
Martijn Coenen44de00c2019-03-22 09:13:17 +01001525 ASSERT_TRUE(IsOk(backups));
1526 ASSERT_EQ(0u, backups->size());
1527 }
Nikita Ioffea82b0a82019-02-15 18:59:47 +00001528}
1529
Nikita Ioffe496a4a42019-03-05 16:32:51 +00001530TEST_F(ApexServiceTest, UnstagePackagesSuccess) {
1531 PrepareTestApexForInstall installer1(GetTestFile("apex.apexd_test.apex"));
1532 PrepareTestApexForInstall installer2(
1533 GetTestFile("apex.apexd_test_different_app.apex"));
1534
1535 if (!installer1.Prepare() || !installer2.Prepare()) {
1536 return;
1537 }
1538
1539 bool ret = false;
1540 std::vector<std::string> pkgs = {installer1.test_file, installer2.test_file};
1541 ASSERT_TRUE(IsOk(service_->stagePackages(pkgs, &ret)));
1542 ASSERT_TRUE(ret);
1543
1544 pkgs = {installer2.test_installed_file};
1545 ASSERT_TRUE(IsOk(service_->unstagePackages(pkgs)));
1546
Mohammad Samiul Islamd428a182019-03-19 14:36:24 +00001547 auto active_packages =
1548 ReadDir(kActiveApexPackagesDataDir, [](auto _) { return true; });
Nikita Ioffe496a4a42019-03-05 16:32:51 +00001549 ASSERT_TRUE(IsOk(active_packages));
1550 ASSERT_THAT(*active_packages,
1551 UnorderedElementsAre(installer1.test_installed_file));
1552}
1553
1554TEST_F(ApexServiceTest, UnstagePackagesFail) {
1555 PrepareTestApexForInstall installer1(GetTestFile("apex.apexd_test.apex"));
1556 PrepareTestApexForInstall installer2(
1557 GetTestFile("apex.apexd_test_different_app.apex"));
1558
1559 if (!installer1.Prepare() || !installer2.Prepare()) {
1560 return;
1561 }
1562
1563 bool ret = false;
1564 std::vector<std::string> pkgs = {installer1.test_file};
1565 ASSERT_TRUE(IsOk(service_->stagePackages(pkgs, &ret)));
1566 ASSERT_TRUE(ret);
1567
1568 pkgs = {installer1.test_installed_file, installer2.test_installed_file};
1569 ASSERT_FALSE(IsOk(service_->unstagePackages(pkgs)));
1570
1571 // Check that first package wasn't unstaged.
Mohammad Samiul Islamd428a182019-03-19 14:36:24 +00001572 auto active_packages =
1573 ReadDir(kActiveApexPackagesDataDir, [](auto _) { return true; });
Nikita Ioffe496a4a42019-03-05 16:32:51 +00001574 ASSERT_TRUE(IsOk(active_packages));
1575 ASSERT_THAT(*active_packages,
1576 UnorderedElementsAre(installer1.test_installed_file));
1577}
1578
Nikita Ioffe9ae986a2019-02-18 22:39:27 +00001579class ApexServiceRollbackTest : public ApexServiceTest {
1580 protected:
1581 void SetUp() override { ApexServiceTest::SetUp(); }
1582
Nikita Ioffef71e02f2019-03-25 16:19:18 +00001583 void PrepareBackup(const std::vector<std::string>& pkgs) {
Nikita Ioffe9ae986a2019-02-18 22:39:27 +00001584 ASSERT_TRUE(IsOk(createDirIfNeeded(std::string(kApexBackupDir), 0700)));
1585 for (const auto& pkg : pkgs) {
Nikita Ioffea4dc3e82019-02-23 17:37:04 +00001586 PrepareTestApexForInstall installer(pkg);
1587 ASSERT_TRUE(installer.Prepare()) << " failed to prepare " << pkg;
1588 const std::string& from = installer.test_file;
1589 std::string to = std::string(kApexBackupDir) + "/" + installer.package +
1590 "@" + std::to_string(installer.version) + ".apex";
Nikita Ioffe9ae986a2019-02-18 22:39:27 +00001591 std::error_code ec;
Nikita Ioffea4dc3e82019-02-23 17:37:04 +00001592 fs::copy(fs::path(from), fs::path(to),
1593 fs::copy_options::create_hard_links, ec);
1594 ASSERT_FALSE(ec) << "Failed to copy " << from << " to " << to << " : "
Nikita Ioffe9ae986a2019-02-18 22:39:27 +00001595 << ec;
1596 }
1597 }
1598
1599 void CheckRollbackWasPerformed(
1600 const std::vector<std::string>& expected_pkgs) {
1601 // First check that /data/apex/active exists and has correct permissions.
1602 struct stat sd;
1603 ASSERT_EQ(0, stat(kActiveApexPackagesDataDir, &sd));
1604 ASSERT_EQ(0750u, sd.st_mode & ALLPERMS);
1605
1606 // Now read content and check it contains expected values.
Mohammad Samiul Islamd428a182019-03-19 14:36:24 +00001607 auto active_pkgs =
1608 ReadDir(kActiveApexPackagesDataDir, [](auto _) { return true; });
Nikita Ioffe9ae986a2019-02-18 22:39:27 +00001609 ASSERT_TRUE(IsOk(active_pkgs));
1610 ASSERT_THAT(*active_pkgs, UnorderedElementsAreArray(expected_pkgs));
1611 }
1612};
1613
1614TEST_F(ApexServiceRollbackTest, AbortActiveSessionSuccessfulRollback) {
Martijn Coenen44de00c2019-03-22 09:13:17 +01001615 if (supports_fs_checkpointing_) {
Nikita Ioffe6f87d542019-04-09 13:09:26 +01001616 GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
Martijn Coenen44de00c2019-03-22 09:13:17 +01001617 }
Nikita Ioffe9ae986a2019-02-18 22:39:27 +00001618 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"));
1619 if (!installer.Prepare()) {
1620 return;
1621 }
1622
1623 auto session = ApexSession::CreateSession(239);
1624 ASSERT_TRUE(IsOk(session));
1625 ASSERT_TRUE(IsOk(session->UpdateStateAndCommit(SessionState::ACTIVATED)));
1626
1627 // Make sure /data/apex/active is non-empty.
1628 bool ret;
1629 ASSERT_TRUE(IsOk(service_->stagePackage(installer.test_file, &ret)));
1630 ASSERT_TRUE(ret);
1631
1632 PrepareBackup({GetTestFile("apex.apexd_test.apex"),
1633 GetTestFile("apex.apexd_test_different_app.apex")});
1634
1635 ASSERT_TRUE(IsOk(service_->abortActiveSession()));
1636
1637 auto pkg1 = StringPrintf("%s/com.android.apex.test_package@1.apex",
1638 kActiveApexPackagesDataDir);
1639 auto pkg2 = StringPrintf("%s/com.android.apex.test_package_2@1.apex",
1640 kActiveApexPackagesDataDir);
1641 SCOPED_TRACE("");
1642 CheckRollbackWasPerformed({pkg1, pkg2});
Nikita Ioffe9ae986a2019-02-18 22:39:27 +00001643 std::vector<ApexSessionInfo> sessions;
1644 ASSERT_TRUE(IsOk(service_->getSessions(&sessions)));
1645 ApexSessionInfo expected = CreateSessionInfo(239);
1646 expected.isRolledBack = true;
1647 ASSERT_THAT(sessions, UnorderedElementsAre(SessionInfoEq(expected)));
1648}
1649
1650TEST_F(ApexServiceRollbackTest, RollbackLastSessionCalledSuccessfulRollback) {
Nikita Ioffe6f87d542019-04-09 13:09:26 +01001651 if (supports_fs_checkpointing_) {
1652 GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
1653 }
1654
Nikita Ioffe9ae986a2019-02-18 22:39:27 +00001655 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"));
1656 if (!installer.Prepare()) {
1657 return;
1658 }
1659
1660 auto session = ApexSession::CreateSession(1543);
1661 ASSERT_TRUE(IsOk(session));
1662 ASSERT_TRUE(IsOk(session->UpdateStateAndCommit(SessionState::ACTIVATED)));
1663
1664 // Make sure /data/apex/active is non-empty.
1665 bool ret;
1666 ASSERT_TRUE(IsOk(service_->stagePackage(installer.test_file, &ret)));
1667 ASSERT_TRUE(ret);
1668
1669 PrepareBackup({GetTestFile("apex.apexd_test.apex")});
1670
Andreas Gampe6e13ff82019-04-01 15:23:50 -07001671 ASSERT_TRUE(IsOk(service_->rollbackActiveSession()));
Nikita Ioffe9ae986a2019-02-18 22:39:27 +00001672
1673 auto pkg = StringPrintf("%s/com.android.apex.test_package@1.apex",
1674 kActiveApexPackagesDataDir);
1675 SCOPED_TRACE("");
1676 CheckRollbackWasPerformed({pkg});
1677}
1678
1679TEST_F(ApexServiceRollbackTest, RollbackLastSessionCalledNoActiveSession) {
1680 // This test simulates a situation that should never happen on user builds:
1681 // abortLastSession was called, but there are no active sessions.
1682 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"));
1683 if (!installer.Prepare()) {
1684 return;
1685 }
1686
1687 // Make sure /data/apex/active is non-empty.
1688 bool ret;
1689 ASSERT_TRUE(IsOk(service_->stagePackage(installer.test_file, &ret)));
1690 ASSERT_TRUE(ret);
1691
1692 PrepareBackup({GetTestFile("apex.apexd_test.apex")});
1693
1694 // Even though backup is there, no sessions are active, hence rollback request
1695 // should fail.
Andreas Gampe6e13ff82019-04-01 15:23:50 -07001696 ASSERT_FALSE(IsOk(service_->rollbackActiveSession()));
Nikita Ioffe9ae986a2019-02-18 22:39:27 +00001697}
1698
1699TEST_F(ApexServiceRollbackTest, RollbackFailsNoBackupFolder) {
Andreas Gampe6e13ff82019-04-01 15:23:50 -07001700 ASSERT_FALSE(IsOk(service_->rollbackActiveSession()));
Nikita Ioffe9ae986a2019-02-18 22:39:27 +00001701}
1702
1703TEST_F(ApexServiceRollbackTest, RollbackFailsNoActivePackagesFolder) {
1704 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"));
Andreas Gampe6e13ff82019-04-01 15:23:50 -07001705 ASSERT_FALSE(IsOk(service_->rollbackActiveSession()));
Nikita Ioffe9ae986a2019-02-18 22:39:27 +00001706}
1707
Nikita Ioffea4dc3e82019-02-23 17:37:04 +00001708TEST_F(ApexServiceRollbackTest, MarkStagedSessionSuccessfulCleanupBackup) {
1709 PrepareBackup({GetTestFile("apex.apexd_test.apex"),
1710 GetTestFile("apex.apexd_test_different_app.apex")});
1711
1712 auto session = ApexSession::CreateSession(101);
1713 ASSERT_TRUE(IsOk(session));
1714 ASSERT_TRUE(IsOk(session->UpdateStateAndCommit(SessionState::ACTIVATED)));
1715
1716 ASSERT_TRUE(IsOk(service_->markStagedSessionSuccessful(101)));
1717
1718 ASSERT_TRUE(fs::is_empty(fs::path(kApexBackupDir)));
1719}
1720
Nikita Ioffe2f6936c2019-02-26 20:03:32 +00001721TEST_F(ApexServiceRollbackTest, ResumesRollback) {
Martijn Coenen44de00c2019-03-22 09:13:17 +01001722 if (supports_fs_checkpointing_) {
Nikita Ioffe6f87d542019-04-09 13:09:26 +01001723 GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
Martijn Coenen44de00c2019-03-22 09:13:17 +01001724 }
Nikita Ioffe2f6936c2019-02-26 20:03:32 +00001725 PrepareBackup({GetTestFile("apex.apexd_test.apex"),
1726 GetTestFile("apex.apexd_test_different_app.apex")});
1727
1728 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"));
1729 if (!installer.Prepare()) {
1730 return;
1731 }
1732
1733 // Make sure /data/apex/active is non-empty.
1734 bool ret;
1735 ASSERT_TRUE(IsOk(service_->stagePackage(installer.test_file, &ret)));
1736 ASSERT_TRUE(ret);
1737
1738 auto session = ApexSession::CreateSession(17239);
1739 ASSERT_TRUE(IsOk(session));
1740 ASSERT_TRUE(
1741 IsOk(session->UpdateStateAndCommit(SessionState::ROLLBACK_IN_PROGRESS)));
1742
Andreas Gampe6e13ff82019-04-01 15:23:50 -07001743 ASSERT_TRUE(IsOk(service_->resumeRollbackIfNeeded()));
Nikita Ioffe2f6936c2019-02-26 20:03:32 +00001744
1745 auto pkg1 = StringPrintf("%s/com.android.apex.test_package@1.apex",
1746 kActiveApexPackagesDataDir);
1747 auto pkg2 = StringPrintf("%s/com.android.apex.test_package_2@1.apex",
1748 kActiveApexPackagesDataDir);
1749 SCOPED_TRACE("");
1750 CheckRollbackWasPerformed({pkg1, pkg2});
1751
1752 std::vector<ApexSessionInfo> sessions;
1753 ASSERT_TRUE(IsOk(service_->getSessions(&sessions)));
1754 ApexSessionInfo expected = CreateSessionInfo(17239);
1755 expected.isRolledBack = true;
1756 ASSERT_THAT(sessions, UnorderedElementsAre(SessionInfoEq(expected)));
1757}
1758
1759TEST_F(ApexServiceRollbackTest, DoesNotResumeRollback) {
Martijn Coenen44de00c2019-03-22 09:13:17 +01001760 if (supports_fs_checkpointing_) {
Nikita Ioffe6f87d542019-04-09 13:09:26 +01001761 GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
Martijn Coenen44de00c2019-03-22 09:13:17 +01001762 }
Nikita Ioffe2f6936c2019-02-26 20:03:32 +00001763 PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"));
1764 if (!installer.Prepare()) {
1765 return;
1766 }
1767
1768 // Make sure /data/apex/active is non-empty.
1769 bool ret;
1770 ASSERT_TRUE(IsOk(service_->stagePackage(installer.test_file, &ret)));
1771 ASSERT_TRUE(ret);
1772
1773 auto session = ApexSession::CreateSession(53);
1774 ASSERT_TRUE(IsOk(session));
1775 ASSERT_TRUE(IsOk(session->UpdateStateAndCommit(SessionState::SUCCESS)));
1776
Andreas Gampe6e13ff82019-04-01 15:23:50 -07001777 ASSERT_TRUE(IsOk(service_->resumeRollbackIfNeeded()));
Nikita Ioffe2f6936c2019-02-26 20:03:32 +00001778
1779 // Check that rollback wasn't resumed.
Mohammad Samiul Islamd428a182019-03-19 14:36:24 +00001780 auto active_pkgs =
1781 ReadDir(kActiveApexPackagesDataDir, [](auto _) { return true; });
Nikita Ioffe2f6936c2019-02-26 20:03:32 +00001782 ASSERT_TRUE(IsOk(active_pkgs));
1783 ASSERT_THAT(*active_pkgs,
1784 UnorderedElementsAre(installer.test_installed_file));
1785
1786 std::vector<ApexSessionInfo> sessions;
1787 ASSERT_TRUE(IsOk(service_->getSessions(&sessions)));
1788 ApexSessionInfo expected = CreateSessionInfo(53);
1789 expected.isSuccess = true;
1790 ASSERT_THAT(sessions, UnorderedElementsAre(SessionInfoEq(expected)));
1791}
1792
Nikita Ioffe6f87d542019-04-09 13:09:26 +01001793TEST_F(ApexServiceRollbackTest, FailsRollback) {
1794 if (supports_fs_checkpointing_) {
1795 GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
1796 }
1797
1798 auto session = ApexSession::CreateSession(53);
1799 ASSERT_TRUE(IsOk(session));
1800 ASSERT_TRUE(IsOk(session->UpdateStateAndCommit(SessionState::ACTIVATED)));
1801
1802 ASSERT_FALSE(IsOk(service_->rollbackActiveSession()));
1803 ApexSessionInfo session_info;
1804 ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(53, &session_info)));
1805 ApexSessionInfo expected = CreateSessionInfo(53);
1806 expected.isRollbackFailed = true;
1807 ASSERT_THAT(session_info, SessionInfoEq(expected));
1808}
1809
1810TEST_F(ApexServiceRollbackTest, RollbackFailedStateRollbackAttemptFails) {
1811 if (supports_fs_checkpointing_) {
1812 GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
1813 }
1814
1815 auto session = ApexSession::CreateSession(17239);
1816 ASSERT_TRUE(IsOk(session));
1817 ASSERT_TRUE(
1818 IsOk(session->UpdateStateAndCommit(SessionState::ROLLBACK_FAILED)));
1819
1820 ASSERT_FALSE(IsOk(service_->rollbackActiveSession()));
1821 ApexSessionInfo session_info;
1822 ASSERT_TRUE(IsOk(service_->getStagedSessionInfo(17239, &session_info)));
1823 ApexSessionInfo expected = CreateSessionInfo(17239);
1824 expected.isRollbackFailed = true;
1825 ASSERT_THAT(session_info, SessionInfoEq(expected));
1826}
1827
Jiyong Park715e23d2019-02-22 22:14:37 +09001828static pid_t GetPidOf(const std::string& name) {
1829 char buf[1024];
1830 const std::string cmd = std::string("pidof -s ") + name;
1831 FILE* cmd_pipe = popen(cmd.c_str(), "r");
1832 if (cmd_pipe == nullptr) {
1833 PLOG(ERROR) << "Cannot open pipe for " << cmd;
1834 return 0;
1835 }
1836 if (fgets(buf, 1024, cmd_pipe) == nullptr) {
1837 PLOG(ERROR) << "Cannot read pipe for " << cmd;
1838 pclose(cmd_pipe);
1839 return 0;
1840 }
1841
1842 pclose(cmd_pipe);
1843 return strtoul(buf, nullptr, 10);
1844}
1845
Nikita Ioffef71e02f2019-03-25 16:19:18 +00001846static void ExecInMountNamespaceOf(pid_t pid,
1847 const std::function<void(pid_t)>& func) {
Jiyong Park715e23d2019-02-22 22:14:37 +09001848 const std::string my_path = "/proc/self/ns/mnt";
1849 android::base::unique_fd my_fd(open(my_path.c_str(), O_RDONLY | O_CLOEXEC));
1850 ASSERT_TRUE(my_fd.get() >= 0);
1851
1852 const std::string target_path =
1853 std::string("/proc/") + std::to_string(pid) + "/ns/mnt";
1854 android::base::unique_fd target_fd(
1855 open(target_path.c_str(), O_RDONLY | O_CLOEXEC));
1856 ASSERT_TRUE(target_fd.get() >= 0);
1857
1858 int res = setns(target_fd.get(), CLONE_NEWNS);
1859 ASSERT_NE(-1, res);
1860
1861 func(pid);
1862
1863 res = setns(my_fd.get(), CLONE_NEWNS);
1864 ASSERT_NE(-1, res);
1865}
1866
1867TEST(ApexdTest, ApexdIsInSameMountNamespaceAsInit) {
1868 std::string ns_apexd;
1869 std::string ns_init;
1870
1871 ExecInMountNamespaceOf(GetPidOf("apexd"), [&](pid_t pid) {
1872 bool res = android::base::Readlink("/proc/self/ns/mnt", &ns_apexd);
1873 ASSERT_TRUE(res);
1874 });
1875
1876 ExecInMountNamespaceOf(1, [&](pid_t pid) {
1877 bool res = android::base::Readlink("/proc/self/ns/mnt", &ns_init);
1878 ASSERT_TRUE(res);
1879 });
1880
1881 ASSERT_EQ(ns_apexd, ns_init);
1882}
1883
1884// These are NOT exhaustive list of early processes be should be enough
1885static const std::vector<const std::string> kEarlyProcesses = {
1886 "servicemanager",
1887 "hwservicemanager",
1888 "vold",
1889 "logd",
1890};
1891
1892TEST(ApexdTest, EarlyProcessesAreInDifferentMountNamespace) {
1893 if (!android::base::GetBoolProperty("ro.apex.updatable", false)) {
1894 return;
1895 }
1896
1897 std::string ns_apexd;
1898
1899 ExecInMountNamespaceOf(GetPidOf("apexd"), [&](pid_t _) {
1900 bool res = android::base::Readlink("/proc/self/ns/mnt", &ns_apexd);
1901 ASSERT_TRUE(res);
1902 });
1903
1904 for (const auto& name : kEarlyProcesses) {
1905 std::string ns_early_process;
1906 ExecInMountNamespaceOf(GetPidOf(name), [&](pid_t _) {
1907 bool res =
1908 android::base::Readlink("/proc/self/ns/mnt", &ns_early_process);
1909 ASSERT_TRUE(res);
1910 });
1911 ASSERT_NE(ns_apexd, ns_early_process);
1912 }
1913}
1914
1915TEST(ApexdTest, ApexIsAPrivateMountPoint) {
1916 std::string mountinfo;
1917 ASSERT_TRUE(
1918 android::base::ReadFileToString("/proc/self/mountinfo", &mountinfo));
1919 bool found_apex_mountpoint = false;
1920 for (const auto& line : android::base::Split(mountinfo, "\n")) {
1921 std::vector<std::string> tokens = android::base::Split(line, " ");
1922 // line format:
1923 // mnt_id parent_mnt_id major:minor source target option propagation_type
1924 // ex) 33 260:19 / /apex rw,nosuid,nodev -
1925 if (tokens.size() >= 7 && tokens[4] == "/apex") {
1926 found_apex_mountpoint = true;
1927 // Make sure that propagation type is set to - which means private
1928 ASSERT_EQ("-", tokens[6]);
1929 }
1930 }
1931 ASSERT_TRUE(found_apex_mountpoint);
1932}
1933
1934static const std::vector<const std::string> kEarlyApexes = {
1935 "/apex/com.android.runtime",
1936 "/apex/com.android.tzdata",
1937};
1938
1939TEST(ApexdTest, ApexesAreActivatedForEarlyProcesses) {
1940 for (const auto& name : kEarlyProcesses) {
1941 pid_t pid = GetPidOf(name);
1942 const std::string path =
1943 std::string("/proc/") + std::to_string(pid) + "/mountinfo";
1944 std::string mountinfo;
1945 ASSERT_TRUE(android::base::ReadFileToString(path.c_str(), &mountinfo));
1946
1947 std::unordered_set<std::string> mountpoints;
1948 for (const auto& line : android::base::Split(mountinfo, "\n")) {
1949 std::vector<std::string> tokens = android::base::Split(line, " ");
1950 // line format:
1951 // mnt_id parent_mnt_id major:minor source target option propagation_type
1952 // ex) 69 33 7:40 / /apex/com.android.conscrypt ro,nodev,noatime -
1953 if (tokens.size() >= 5) {
1954 // token[4] is the target mount point
1955 mountpoints.emplace(tokens[4]);
1956 }
1957 }
1958 for (const auto& apex_name : kEarlyApexes) {
1959 ASSERT_NE(mountpoints.end(), mountpoints.find(apex_name));
1960 }
1961 }
1962}
1963
Nikita Ioffedf074412019-03-20 07:56:52 +00001964class ApexShimUpdateTest : public ApexServiceTest {
1965 protected:
Nikita Ioffe69a1bc52019-03-29 14:55:29 +00001966 void SetUp() override {
1967 ApexServiceTest::SetUp();
1968
Nikita Ioffefa7b5da2019-04-10 12:15:53 +01001969 // Assert that shim apex is pre-installed.
1970 std::vector<ApexInfo> list;
1971 ASSERT_TRUE(IsOk(service_->getAllPackages(&list)));
1972 ApexInfo expected;
1973 expected.packageName = "com.android.apex.cts.shim";
1974 expected.packagePath = "/system/apex/com.android.apex.cts.shim.apex";
1975 expected.versionCode = 1;
1976 expected.isFactory = true;
1977 expected.isActive = true;
1978 ASSERT_THAT(list, Contains(ApexInfoEq(expected)));
Nikita Ioffedf074412019-03-20 07:56:52 +00001979 }
1980};
1981
1982TEST_F(ApexShimUpdateTest, UpdateToV2Success) {
1983 PrepareTestApexForInstall installer(
1984 GetTestFile("com.android.apex.cts.shim.v2.apex"));
1985
1986 if (!installer.Prepare()) {
1987 FAIL() << GetDebugStr(&installer);
1988 }
1989
1990 bool success;
1991 ASSERT_TRUE(IsOk(service_->stagePackage(installer.test_file, &success)));
1992 ASSERT_TRUE(success);
1993}
1994
Nikita Ioffed9a25d42019-03-26 01:37:03 +00001995TEST_F(ApexShimUpdateTest, UpdateToV2FailureWrongSHA512) {
1996 PrepareTestApexForInstall installer(
1997 GetTestFile("com.android.apex.cts.shim.v2_wrong_sha.apex"));
1998
1999 if (!installer.Prepare()) {
2000 FAIL() << GetDebugStr(&installer);
2001 }
2002
2003 bool success;
Nikita Ioffe98054d72019-04-03 14:18:22 +01002004 const auto& status = service_->stagePackage(installer.test_file, &success);
2005 ASSERT_FALSE(IsOk(status));
2006 const std::string& error_message =
2007 std::string(status.exceptionMessage().c_str());
2008 ASSERT_THAT(error_message, HasSubstr("has unexpected SHA512 hash"));
Nikita Ioffed9a25d42019-03-26 01:37:03 +00002009}
2010
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002011TEST_F(ApexShimUpdateTest, SubmitStagedSesssionFailureHasPreInstallHook) {
Nikita Ioffe69a1bc52019-03-29 14:55:29 +00002012 PrepareTestApexForInstall installer(
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002013 GetTestFile("com.android.apex.cts.shim.v2_with_pre_install_hook.apex"),
2014 "/data/app-staging/session_23", "staging_data_file");
Nikita Ioffe69a1bc52019-03-29 14:55:29 +00002015
2016 if (!installer.Prepare()) {
2017 FAIL() << GetDebugStr(&installer);
2018 }
2019
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002020 ApexInfoList list;
Nikita Ioffe69a1bc52019-03-29 14:55:29 +00002021 bool success;
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002022 ASSERT_TRUE(IsOk(service_->submitStagedSession(23, {}, &list, &success)));
2023 ASSERT_FALSE(success);
Nikita Ioffe69a1bc52019-03-29 14:55:29 +00002024}
2025
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002026TEST_F(ApexShimUpdateTest, SubmitStagedSessionFailureHasPostInstallHook) {
Nikita Ioffe69a1bc52019-03-29 14:55:29 +00002027 PrepareTestApexForInstall installer(
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002028 GetTestFile("com.android.apex.cts.shim.v2_with_post_install_hook.apex"),
2029 "/data/app-staging/session_43", "staging_data_file");
Nikita Ioffe69a1bc52019-03-29 14:55:29 +00002030
2031 if (!installer.Prepare()) {
2032 FAIL() << GetDebugStr(&installer);
2033 }
2034
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002035 ApexInfoList list;
Nikita Ioffe69a1bc52019-03-29 14:55:29 +00002036 bool success;
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002037 ASSERT_TRUE(IsOk(service_->submitStagedSession(43, {}, &list, &success)));
2038 ASSERT_FALSE(success);
Nikita Ioffe69a1bc52019-03-29 14:55:29 +00002039}
2040
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002041TEST_F(ApexShimUpdateTest, SubmitStagedSessionFailureAdditionalFile) {
Nikita Ioffe2cbca0e2019-03-27 19:12:11 +00002042 PrepareTestApexForInstall installer(
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002043 GetTestFile("com.android.apex.cts.shim.v2_additional_file.apex"),
2044 "/data/app-staging/session_41", "staging_data_file");
Nikita Ioffe2cbca0e2019-03-27 19:12:11 +00002045 if (!installer.Prepare()) {
2046 FAIL() << GetDebugStr(&installer);
2047 }
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002048
2049 ApexInfoList list;
Nikita Ioffe98054d72019-04-03 14:18:22 +01002050 bool success;
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002051 ASSERT_TRUE(IsOk(service_->submitStagedSession(41, {}, &list, &success)));
2052 ASSERT_FALSE(success);
Nikita Ioffe2cbca0e2019-03-27 19:12:11 +00002053}
2054
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002055TEST_F(ApexShimUpdateTest, SubmitStagedSessionFailureAdditionalFolder) {
Nikita Ioffe2cbca0e2019-03-27 19:12:11 +00002056 PrepareTestApexForInstall installer(
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002057 GetTestFile("com.android.apex.cts.shim.v2_additional_folder.apex"),
2058 "/data/app-staging/session_42", "staging_data_file");
Nikita Ioffe2cbca0e2019-03-27 19:12:11 +00002059 if (!installer.Prepare()) {
2060 FAIL() << GetDebugStr(&installer);
2061 }
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002062
2063 ApexInfoList list;
Nikita Ioffe98054d72019-04-03 14:18:22 +01002064 bool success;
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002065 ASSERT_TRUE(IsOk(service_->submitStagedSession(42, {}, &list, &success)));
2066 ASSERT_FALSE(success);
Nikita Ioffe2cbca0e2019-03-27 19:12:11 +00002067}
2068
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002069TEST_F(ApexServiceTest, SubmitStagedSessionCorruptApexFails) {
Martijn Coenen2caabb42019-04-02 11:42:02 +02002070 PrepareTestApexForInstall installer(
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002071 GetTestFile("apex.apexd_test_corrupt_apex.apex"),
2072 "/data/app-staging/session_57", "staging_data_file");
Martijn Coenen2caabb42019-04-02 11:42:02 +02002073
2074 if (!installer.Prepare()) {
2075 FAIL() << GetDebugStr(&installer);
2076 }
2077
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002078 ApexInfoList list;
Martijn Coenen2caabb42019-04-02 11:42:02 +02002079 bool success;
Nikita Ioffe54e24cd2019-04-05 17:04:11 +01002080 ASSERT_TRUE(IsOk(service_->submitStagedSession(57, {}, &list, &success)));
2081 ASSERT_FALSE(success);
Martijn Coenen2caabb42019-04-02 11:42:02 +02002082}
2083
Nikita Ioffea67b3cd2019-04-29 11:24:40 +01002084// Following test case piggybacks on logic in ApexServiceActivationSuccessTest
2085// in order to use mounted apex as flattened one.
2086TEST_F(ApexServiceActivationSuccessTest, StageFailsFlattenedApex) {
2087 ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
2088 << GetDebugStr(installer_.get());
2089
2090 StatusOr<ApexFile> flattened_apex =
2091 ApexFile::Open(StringPrintf("/apex/%s", installer_->package.c_str()));
2092 ASSERT_TRUE(IsOk(flattened_apex));
2093 ASSERT_TRUE(flattened_apex->IsFlattened());
2094
2095 bool success;
2096 const auto& status =
2097 service_->stagePackage(flattened_apex->GetPath(), &success);
2098 ASSERT_FALSE(IsOk(status));
2099 const std::string& error_message =
2100 std::string(status.exceptionMessage().c_str());
2101 ASSERT_THAT(error_message, HasSubstr("Can't upgrade flattened apex"));
2102}
2103
Nikita Ioffe61a9b532019-02-14 17:50:00 +00002104class LogTestToLogcat : public ::testing::EmptyTestEventListener {
2105 void OnTestStart(const ::testing::TestInfo& test_info) override {
Andreas Gampe5ec47c52018-11-14 14:33:53 -08002106#ifdef __ANDROID__
2107 using base::LogId;
2108 using base::LogSeverity;
2109 using base::StringPrintf;
2110 base::LogdLogger l;
2111 std::string msg =
2112 StringPrintf("=== %s::%s (%s:%d)", test_info.test_case_name(),
2113 test_info.name(), test_info.file(), test_info.line());
2114 l(LogId::MAIN, LogSeverity::INFO, "apexservice_test", __FILE__, __LINE__,
2115 msg.c_str());
2116#else
Andreas Gampe74a89562018-11-16 14:41:47 -08002117 UNUSED(test_info);
Andreas Gampe5ec47c52018-11-14 14:33:53 -08002118#endif
2119 }
2120};
2121
Andreas Gampe35e80932018-10-29 12:56:53 -07002122} // namespace apex
2123} // namespace android
2124
2125int main(int argc, char** argv) {
2126 android::base::InitLogging(argv, &android::base::StderrLogger);
2127 ::testing::InitGoogleTest(&argc, argv);
Nikita Ioffe61a9b532019-02-14 17:50:00 +00002128 ::testing::UnitTest::GetInstance()->listeners().Append(
Andreas Gampe5ec47c52018-11-14 14:33:53 -08002129 new android::apex::LogTestToLogcat());
Andreas Gampe35e80932018-10-29 12:56:53 -07002130 return RUN_ALL_TESTS();
2131}