blob: 3112e4a1f3681e7d75337d9cb446f40fc2cb1d5d [file] [log] [blame]
Ben Chan1e5a0cb2012-03-22 00:41:52 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Ben Chanf51ff002011-04-25 12:41:57 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Chan5ccd9fe2013-11-13 18:28:27 -08005#include "cros-disks/disk_manager.h"
Ben Chan29be9152011-07-25 14:39:48 -07006
Ben Chanf51ff002011-04-25 12:41:57 -07007#include <sys/mount.h>
Ben Chanbdc39742011-05-11 17:51:26 -07008
Ben Chan5e3ca672014-08-25 15:53:58 -07009#include <memory>
10
Ben Chancd8fda42014-09-05 08:21:06 -070011#include <base/files/file_util.h>
Allen Webb57f0c052017-09-20 14:11:21 -070012#include <base/logging.h>
Ben Chanb5d71222012-10-03 12:55:16 -070013#include <base/stl_util.h>
Ben Chan1e5a0cb2012-03-22 00:41:52 -070014#include <gmock/gmock.h>
Ben Chanbdc39742011-05-11 17:51:26 -070015#include <gtest/gtest.h>
16
Ben Chan5ccd9fe2013-11-13 18:28:27 -080017#include "cros-disks/device_ejector.h"
Ben Chanbdc39742011-05-11 17:51:26 -070018#include "cros-disks/disk.h"
Ben Chan5ccd9fe2013-11-13 18:28:27 -080019#include "cros-disks/exfat_mounter.h"
Ben Chane31d2aa2011-06-15 13:52:59 -070020#include "cros-disks/filesystem.h"
Ben Chanbe2b4a72011-11-08 13:42:23 -080021#include "cros-disks/metrics.h"
Ben Chane31d2aa2011-06-15 13:52:59 -070022#include "cros-disks/mounter.h"
Ben Chan5ccd9fe2013-11-13 18:28:27 -080023#include "cros-disks/ntfs_mounter.h"
Ben Chan29be9152011-07-25 14:39:48 -070024#include "cros-disks/platform.h"
Ben Chanf51ff002011-04-25 12:41:57 -070025
Ben Chan190d3cf2011-07-07 09:38:48 -070026using std::map;
27using std::string;
Ben Chan5e3ca672014-08-25 15:53:58 -070028using std::unique_ptr;
Ben Chan190d3cf2011-07-07 09:38:48 -070029using std::vector;
Ben Chan1e5a0cb2012-03-22 00:41:52 -070030using testing::Return;
31using testing::_;
Ben Chan190d3cf2011-07-07 09:38:48 -070032
Ben Chan460439f2011-09-13 09:16:28 -070033namespace {
Ben Chanf51ff002011-04-25 12:41:57 -070034
Ben Chan460439f2011-09-13 09:16:28 -070035const char kMountRootDirectory[] = "/media/removable";
36
37} // namespace
38
39namespace cros_disks {
Ben Chan8dcede82011-07-25 20:56:13 -070040
Ben Chan1e5a0cb2012-03-22 00:41:52 -070041// A mock device ejector class for testing the disk manager class.
42class MockDeviceEjector : public DeviceEjector {
43 public:
Ben Chan445852f2017-10-02 23:00:16 -070044 MockDeviceEjector() : DeviceEjector(nullptr) {}
Ben Chan1e5a0cb2012-03-22 00:41:52 -070045
46 MOCK_METHOD1(Eject, bool(const string& device_path));
47};
48
Ben Chanf51ff002011-04-25 12:41:57 -070049class DiskManagerTest : public ::testing::Test {
Ben Chan29be9152011-07-25 14:39:48 -070050 public:
Ben Chan8dcede82011-07-25 20:56:13 -070051 DiskManagerTest()
Ben Chan1e5a0cb2012-03-22 00:41:52 -070052 : manager_(kMountRootDirectory, &platform_, &metrics_, &device_ejector_) {
Ben Chan29be9152011-07-25 14:39:48 -070053 }
54
Ben Chane31d2aa2011-06-15 13:52:59 -070055 protected:
Ben Chanbe2b4a72011-11-08 13:42:23 -080056 Metrics metrics_;
Ben Chan29be9152011-07-25 14:39:48 -070057 Platform platform_;
Ben Chan1e5a0cb2012-03-22 00:41:52 -070058 MockDeviceEjector device_ejector_;
Ben Chane31d2aa2011-06-15 13:52:59 -070059 DiskManager manager_;
Ben Chanf51ff002011-04-25 12:41:57 -070060};
61
Ben Chanaf455a02013-01-08 15:29:22 -080062TEST_F(DiskManagerTest, CreateExFATMounter) {
63 Disk disk;
Ben Chanff92fa32017-10-17 16:17:15 -070064 disk.device_file = "/dev/sda1";
Ben Chanaf455a02013-01-08 15:29:22 -080065
66 Filesystem filesystem("exfat");
67 filesystem.set_mounter_type(ExFATMounter::kMounterType);
68
69 string target_path = "/media/disk";
Ben Chan63ec9c42014-04-21 19:13:23 -070070 vector<string> options = {"rw", "nodev", "noexec", "nosuid"};
Ben Chanaf455a02013-01-08 15:29:22 -080071
Ben Chan5e3ca672014-08-25 15:53:58 -070072 unique_ptr<Mounter> mounter(
73 manager_.CreateMounter(disk, filesystem, target_path, options));
Ben Chan44e7ea62014-08-29 18:13:37 -070074 EXPECT_NE(nullptr, mounter.get());
Ben Chanaf455a02013-01-08 15:29:22 -080075 EXPECT_EQ(filesystem.mount_type(), mounter->filesystem_type());
Ben Chanff92fa32017-10-17 16:17:15 -070076 EXPECT_EQ(disk.device_file, mounter->source_path());
Ben Chanaf455a02013-01-08 15:29:22 -080077 EXPECT_EQ(target_path, mounter->target_path());
Jorge Lucangeli Obesa4d01112013-02-11 21:28:16 -080078 EXPECT_EQ("rw,nodev,noexec,nosuid", mounter->mount_options().ToString());
Ben Chanaf455a02013-01-08 15:29:22 -080079}
80
Ben Chanb1ac5a82011-08-02 17:53:55 -070081TEST_F(DiskManagerTest, CreateNTFSMounter) {
82 Disk disk;
Ben Chanff92fa32017-10-17 16:17:15 -070083 disk.device_file = "/dev/sda1";
Ben Chanb1ac5a82011-08-02 17:53:55 -070084
85 Filesystem filesystem("ntfs");
86 filesystem.set_mounter_type(NTFSMounter::kMounterType);
87
88 string target_path = "/media/disk";
Ben Chan63ec9c42014-04-21 19:13:23 -070089 vector<string> options = {"rw", "nodev", "noexec", "nosuid"};
Ben Chanb1ac5a82011-08-02 17:53:55 -070090
Ben Chan5e3ca672014-08-25 15:53:58 -070091 unique_ptr<Mounter> mounter(
92 manager_.CreateMounter(disk, filesystem, target_path, options));
Ben Chan44e7ea62014-08-29 18:13:37 -070093 EXPECT_NE(nullptr, mounter.get());
Ben Chane31d2aa2011-06-15 13:52:59 -070094 EXPECT_EQ(filesystem.mount_type(), mounter->filesystem_type());
Ben Chanff92fa32017-10-17 16:17:15 -070095 EXPECT_EQ(disk.device_file, mounter->source_path());
Ben Chane31d2aa2011-06-15 13:52:59 -070096 EXPECT_EQ(target_path, mounter->target_path());
Jorge Lucangeli Obesa4d01112013-02-11 21:28:16 -080097 EXPECT_EQ("rw,nodev,noexec,nosuid", mounter->mount_options().ToString());
Ben Chane31d2aa2011-06-15 13:52:59 -070098}
99
100TEST_F(DiskManagerTest, CreateSystemMounter) {
101 Disk disk;
Ben Chanff92fa32017-10-17 16:17:15 -0700102 disk.device_file = "/dev/sda1";
Ben Chane31d2aa2011-06-15 13:52:59 -0700103
104 Filesystem filesystem("vfat");
Ben Chan1bea08e2011-06-27 16:59:09 -0700105 filesystem.AddExtraMountOption("utf8");
106 filesystem.AddExtraMountOption("shortname=mixed");
Ben Chane31d2aa2011-06-15 13:52:59 -0700107
Ben Chan190d3cf2011-07-07 09:38:48 -0700108 string target_path = "/media/disk";
Ben Chan63ec9c42014-04-21 19:13:23 -0700109 vector<string> options = {"rw", "nodev", "noexec", "nosuid"};
Ben Chane31d2aa2011-06-15 13:52:59 -0700110
Ben Chan5e3ca672014-08-25 15:53:58 -0700111 unique_ptr<Mounter> mounter(
112 manager_.CreateMounter(disk, filesystem, target_path, options));
Ben Chan44e7ea62014-08-29 18:13:37 -0700113 EXPECT_NE(nullptr, mounter.get());
Ben Chane31d2aa2011-06-15 13:52:59 -0700114 EXPECT_EQ(filesystem.mount_type(), mounter->filesystem_type());
Ben Chanff92fa32017-10-17 16:17:15 -0700115 EXPECT_EQ(disk.device_file, mounter->source_path());
Ben Chane31d2aa2011-06-15 13:52:59 -0700116 EXPECT_EQ(target_path, mounter->target_path());
Jorge Lucangeli Obesa4d01112013-02-11 21:28:16 -0800117 EXPECT_EQ("utf8,shortname=mixed,rw,nodev,noexec,nosuid",
Ben Chan8dcede82011-07-25 20:56:13 -0700118 mounter->mount_options().ToString());
Ben Chane31d2aa2011-06-15 13:52:59 -0700119}
120
Ben Chanf51ff002011-04-25 12:41:57 -0700121TEST_F(DiskManagerTest, EnumerateDisks) {
Ben Chan190d3cf2011-07-07 09:38:48 -0700122 vector<Disk> disks = manager_.EnumerateDisks();
Ben Chane31d2aa2011-06-15 13:52:59 -0700123}
124
Ben Chanf51ff002011-04-25 12:41:57 -0700125TEST_F(DiskManagerTest, GetDiskByDevicePath) {
Allen Webb57f0c052017-09-20 14:11:21 -0700126 vector<Disk> disks = manager_.EnumerateDisks();
127 if (disks.empty()) {
128 LOG(WARNING) << "No disks found to test.";
129 }
Ben Chanf51ff002011-04-25 12:41:57 -0700130
Allen Webb57f0c052017-09-20 14:11:21 -0700131 for (const auto& found_disk : disks) {
Ben Chanff92fa32017-10-17 16:17:15 -0700132 string device_path = found_disk.device_file;
Allen Webb57f0c052017-09-20 14:11:21 -0700133 LOG(INFO) << "Using device_path: " << device_path << "\n";
134
135 Disk disk;
136 EXPECT_TRUE(manager_.GetDiskByDevicePath(device_path, &disk));
Ben Chanff92fa32017-10-17 16:17:15 -0700137 EXPECT_EQ(device_path, disk.device_file);
Allen Webb57f0c052017-09-20 14:11:21 -0700138 }
Ben Chanf51ff002011-04-25 12:41:57 -0700139}
140
141TEST_F(DiskManagerTest, GetDiskByNonexistentDevicePath) {
Ben Chanf51ff002011-04-25 12:41:57 -0700142 Disk disk;
Ben Chan190d3cf2011-07-07 09:38:48 -0700143 string device_path = "/dev/nonexistent-path";
Ben Chane31d2aa2011-06-15 13:52:59 -0700144 EXPECT_FALSE(manager_.GetDiskByDevicePath(device_path, &disk));
Ben Chanf51ff002011-04-25 12:41:57 -0700145}
146
Ben Chanb092d752011-07-13 11:44:38 -0700147TEST_F(DiskManagerTest, GetFilesystem) {
Ben Chan44e7ea62014-08-29 18:13:37 -0700148 EXPECT_EQ(nullptr, manager_.GetFilesystem("nonexistent-fs"));
Ben Chanb092d752011-07-13 11:44:38 -0700149
150 Filesystem normal_fs("normal-fs");
Ben Chan44e7ea62014-08-29 18:13:37 -0700151 EXPECT_EQ(nullptr, manager_.GetFilesystem(normal_fs.type()));
Ben Chanb092d752011-07-13 11:44:38 -0700152 manager_.RegisterFilesystem(normal_fs);
Ben Chan44e7ea62014-08-29 18:13:37 -0700153 EXPECT_NE(nullptr, manager_.GetFilesystem(normal_fs.type()));
Ben Chanb092d752011-07-13 11:44:38 -0700154}
155
Ben Chane31d2aa2011-06-15 13:52:59 -0700156TEST_F(DiskManagerTest, RegisterFilesystem) {
Ben Chan190d3cf2011-07-07 09:38:48 -0700157 map<string, Filesystem>& filesystems = manager_.filesystems_;
Ben Chane31d2aa2011-06-15 13:52:59 -0700158 EXPECT_EQ(0, filesystems.size());
159 EXPECT_TRUE(filesystems.find("nonexistent") == filesystems.end());
160
161 Filesystem fat_fs("fat");
162 fat_fs.set_accepts_user_and_group_id(true);
163 manager_.RegisterFilesystem(fat_fs);
164 EXPECT_EQ(1, filesystems.size());
165 EXPECT_TRUE(filesystems.find(fat_fs.type()) != filesystems.end());
166
167 Filesystem vfat_fs("vfat");
168 vfat_fs.set_accepts_user_and_group_id(true);
169 manager_.RegisterFilesystem(vfat_fs);
170 EXPECT_EQ(2, filesystems.size());
171 EXPECT_TRUE(filesystems.find(vfat_fs.type()) != filesystems.end());
172}
173
Ben Chan8dcede82011-07-25 20:56:13 -0700174TEST_F(DiskManagerTest, CanMount) {
175 EXPECT_TRUE(manager_.CanMount("/dev/sda1"));
176 EXPECT_TRUE(manager_.CanMount("/devices/block/sda/sda1"));
177 EXPECT_TRUE(manager_.CanMount("/sys/devices/block/sda/sda1"));
178 EXPECT_FALSE(manager_.CanMount("/media/removable/disk1"));
179 EXPECT_FALSE(manager_.CanMount("/media/removable/disk1/"));
180 EXPECT_FALSE(manager_.CanMount("/media/removable/disk 1"));
181 EXPECT_FALSE(manager_.CanMount("/media/archive/test.zip"));
182 EXPECT_FALSE(manager_.CanMount("/media/archive/test.zip/"));
183 EXPECT_FALSE(manager_.CanMount("/media/archive/test 1.zip"));
184 EXPECT_FALSE(manager_.CanMount("/media/removable/disk1/test.zip"));
185 EXPECT_FALSE(manager_.CanMount("/media/removable/disk1/test 1.zip"));
186 EXPECT_FALSE(manager_.CanMount("/media/removable/disk1/dir1/test.zip"));
187 EXPECT_FALSE(manager_.CanMount("/media/removable/test.zip/test1.zip"));
188 EXPECT_FALSE(manager_.CanMount("/home/chronos/user/Downloads/test1.zip"));
Ben Chan16d85862013-05-28 20:30:30 -0700189 EXPECT_FALSE(manager_.CanMount("/home/chronos/user/GCache/test1.zip"));
Ben Chande0e3f62017-09-26 06:28:39 -0700190 EXPECT_FALSE(
191 manager_.CanMount("/home/chronos"
192 "/u-0123456789abcdef0123456789abcdef01234567"
193 "/Downloads/test1.zip"));
194 EXPECT_FALSE(
195 manager_.CanMount("/home/chronos"
196 "/u-0123456789abcdef0123456789abcdef01234567"
197 "/GCache/test1.zip"));
Ben Chan8dcede82011-07-25 20:56:13 -0700198 EXPECT_FALSE(manager_.CanMount(""));
199 EXPECT_FALSE(manager_.CanMount("/tmp"));
200 EXPECT_FALSE(manager_.CanMount("/media/removable"));
201 EXPECT_FALSE(manager_.CanMount("/media/removable/"));
202 EXPECT_FALSE(manager_.CanMount("/media/archive"));
203 EXPECT_FALSE(manager_.CanMount("/media/archive/"));
204 EXPECT_FALSE(manager_.CanMount("/home/chronos/user/Downloads"));
205 EXPECT_FALSE(manager_.CanMount("/home/chronos/user/Downloads/"));
Ben Chanf51ff002011-04-25 12:41:57 -0700206}
207
Ben Chan8dcede82011-07-25 20:56:13 -0700208TEST_F(DiskManagerTest, CanUnmount) {
209 EXPECT_TRUE(manager_.CanUnmount("/dev/sda1"));
210 EXPECT_TRUE(manager_.CanUnmount("/devices/block/sda/sda1"));
211 EXPECT_TRUE(manager_.CanUnmount("/sys/devices/block/sda/sda1"));
212 EXPECT_TRUE(manager_.CanUnmount("/media/removable/disk1"));
213 EXPECT_TRUE(manager_.CanUnmount("/media/removable/disk1/"));
214 EXPECT_TRUE(manager_.CanUnmount("/media/removable/disk 1"));
215 EXPECT_FALSE(manager_.CanUnmount("/media/archive/test.zip"));
216 EXPECT_FALSE(manager_.CanUnmount("/media/archive/test.zip/"));
217 EXPECT_FALSE(manager_.CanUnmount("/media/archive/test 1.zip"));
218 EXPECT_FALSE(manager_.CanUnmount("/media/removable/disk1/test.zip"));
219 EXPECT_FALSE(manager_.CanUnmount("/media/removable/disk1/test 1.zip"));
220 EXPECT_FALSE(manager_.CanUnmount("/media/removable/disk1/dir1/test.zip"));
221 EXPECT_FALSE(manager_.CanUnmount("/media/removable/test.zip/test1.zip"));
222 EXPECT_FALSE(manager_.CanUnmount("/home/chronos/user/Downloads/test1.zip"));
Ben Chan16d85862013-05-28 20:30:30 -0700223 EXPECT_FALSE(manager_.CanUnmount("/home/chronos/user/GCache/test1.zip"));
Ben Chande0e3f62017-09-26 06:28:39 -0700224 EXPECT_FALSE(
225 manager_.CanUnmount("/home/chronos"
226 "/u-0123456789abcdef0123456789abcdef01234567"
227 "/Downloads/test1.zip"));
228 EXPECT_FALSE(
229 manager_.CanUnmount("/home/chronos"
230 "/u-0123456789abcdef0123456789abcdef01234567"
231 "/GCache/test1.zip"));
Ben Chan8dcede82011-07-25 20:56:13 -0700232 EXPECT_FALSE(manager_.CanUnmount(""));
233 EXPECT_FALSE(manager_.CanUnmount("/tmp"));
234 EXPECT_FALSE(manager_.CanUnmount("/media/removable"));
235 EXPECT_FALSE(manager_.CanUnmount("/media/removable/"));
236 EXPECT_FALSE(manager_.CanUnmount("/media/archive"));
237 EXPECT_FALSE(manager_.CanUnmount("/media/archive/"));
238 EXPECT_FALSE(manager_.CanUnmount("/home/chronos/user/Downloads"));
239 EXPECT_FALSE(manager_.CanUnmount("/home/chronos/user/Downloads/"));
240}
241
242TEST_F(DiskManagerTest, DoMountDiskWithNonexistentSourcePath) {
243 string filesystem_type = "ext3";
244 string source_path = "/dev/nonexistent-path";
245 string mount_path = "/tmp/cros-disks-test";
Ben Chan190d3cf2011-07-07 09:38:48 -0700246 vector<string> options;
Tatsuhisa Yamaguchi5a6a3032016-08-19 20:03:54 +0900247 MountOptions applied_options;
Ben Chanfcb2fc02011-11-21 09:44:07 -0800248 EXPECT_EQ(MOUNT_ERROR_INVALID_DEVICE_PATH,
Ben Chande0e3f62017-09-26 06:28:39 -0700249 manager_.DoMount(source_path, filesystem_type, options, mount_path,
250 &applied_options));
Ben Chan8dcede82011-07-25 20:56:13 -0700251}
252
253TEST_F(DiskManagerTest, DoUnmountDiskWithInvalidUnmountOptions) {
254 string source_path = "/dev/nonexistent-path";
Ben Chan63ec9c42014-04-21 19:13:23 -0700255 vector<string> options = {"invalid-unmount-option"};
Ben Chanfcb2fc02011-11-21 09:44:07 -0800256 EXPECT_EQ(MOUNT_ERROR_INVALID_UNMOUNT_OPTIONS,
Ben Chan8dcede82011-07-25 20:56:13 -0700257 manager_.DoUnmount(source_path, options));
Ben Chanf51ff002011-04-25 12:41:57 -0700258}
259
Ben Chanb5d71222012-10-03 12:55:16 -0700260TEST_F(DiskManagerTest, ScheduleEjectOnUnmount) {
261 string mount_path = "/media/removable/disk";
262 Disk disk;
Ben Chanff92fa32017-10-17 16:17:15 -0700263 disk.device_file = "/dev/sr0";
Ben Chanb5d71222012-10-03 12:55:16 -0700264 EXPECT_FALSE(manager_.ScheduleEjectOnUnmount(mount_path, disk));
265 EXPECT_FALSE(ContainsKey(manager_.devices_to_eject_on_unmount_, mount_path));
266
Ben Chanff92fa32017-10-17 16:17:15 -0700267 disk.media_type = DEVICE_MEDIA_OPTICAL_DISC;
Ben Chanb5d71222012-10-03 12:55:16 -0700268 EXPECT_TRUE(manager_.ScheduleEjectOnUnmount(mount_path, disk));
269 EXPECT_TRUE(ContainsKey(manager_.devices_to_eject_on_unmount_, mount_path));
270
Ben Chanff92fa32017-10-17 16:17:15 -0700271 disk.media_type = DEVICE_MEDIA_DVD;
Ben Chanb5d71222012-10-03 12:55:16 -0700272 manager_.devices_to_eject_on_unmount_.clear();
273 EXPECT_TRUE(manager_.ScheduleEjectOnUnmount(mount_path, disk));
274 EXPECT_TRUE(ContainsKey(manager_.devices_to_eject_on_unmount_, mount_path));
Ben Chan1e5a0cb2012-03-22 00:41:52 -0700275}
276
Ben Chanb5d71222012-10-03 12:55:16 -0700277TEST_F(DiskManagerTest, EjectDeviceOfMountPath) {
278 string mount_path = "/media/removable/disk";
279 string device_file = "/dev/sr0";
280 manager_.devices_to_eject_on_unmount_[mount_path] = device_file;
281 EXPECT_CALL(device_ejector_, Eject(_)).WillOnce(Return(true));
282 EXPECT_TRUE(manager_.EjectDeviceOfMountPath(mount_path));
283 EXPECT_FALSE(ContainsKey(manager_.devices_to_eject_on_unmount_, mount_path));
284}
285
286TEST_F(DiskManagerTest, EjectDeviceOfMountPathWhenEjectFailed) {
287 string mount_path = "/media/removable/disk";
288 string device_file = "/dev/sr0";
289 manager_.devices_to_eject_on_unmount_[mount_path] = device_file;
290 EXPECT_CALL(device_ejector_, Eject(_)).WillOnce(Return(false));
291 EXPECT_FALSE(manager_.EjectDeviceOfMountPath(mount_path));
292 EXPECT_FALSE(ContainsKey(manager_.devices_to_eject_on_unmount_, mount_path));
293}
294
295TEST_F(DiskManagerTest, EjectDeviceOfMountPathWhenExplicitlyDisabled) {
296 string mount_path = "/media/removable/disk";
297 string device_file = "/dev/sr0";
298 manager_.devices_to_eject_on_unmount_[mount_path] = device_file;
299 manager_.eject_device_on_unmount_ = false;
Ben Chan1e5a0cb2012-03-22 00:41:52 -0700300 EXPECT_CALL(device_ejector_, Eject(_)).Times(0);
Ben Chanb5d71222012-10-03 12:55:16 -0700301 EXPECT_FALSE(manager_.EjectDeviceOfMountPath(mount_path));
302 EXPECT_FALSE(ContainsKey(manager_.devices_to_eject_on_unmount_, mount_path));
303}
304
305TEST_F(DiskManagerTest, EjectDeviceOfMountPathWhenMountPathExcluded) {
306 EXPECT_CALL(device_ejector_, Eject(_)).Times(0);
307 EXPECT_FALSE(manager_.EjectDeviceOfMountPath("/media/removable/disk"));
Ben Chan1e5a0cb2012-03-22 00:41:52 -0700308}
309
Ben Chanf51ff002011-04-25 12:41:57 -0700310} // namespace cros_disks