blob: 9263dfbf4d9795d49c194b6b6554c1cb4404074c [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 Chan97e20d42014-02-05 18:38:07 -080011#include <base/files/file_path.h>
Ben Chancd8fda42014-09-05 08:21:06 -070012#include <base/files/file_util.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"
20#include "cros-disks/external_mounter.h"
Ben Chane31d2aa2011-06-15 13:52:59 -070021#include "cros-disks/filesystem.h"
Ben Chanbe2b4a72011-11-08 13:42:23 -080022#include "cros-disks/metrics.h"
Ben Chane31d2aa2011-06-15 13:52:59 -070023#include "cros-disks/mounter.h"
Ben Chan5ccd9fe2013-11-13 18:28:27 -080024#include "cros-disks/ntfs_mounter.h"
Ben Chan29be9152011-07-25 14:39:48 -070025#include "cros-disks/platform.h"
Ben Chanf51ff002011-04-25 12:41:57 -070026
Ben Chan190d3cf2011-07-07 09:38:48 -070027using std::map;
28using std::string;
Ben Chan5e3ca672014-08-25 15:53:58 -070029using std::unique_ptr;
Ben Chan190d3cf2011-07-07 09:38:48 -070030using std::vector;
Ben Chan1e5a0cb2012-03-22 00:41:52 -070031using testing::Return;
32using testing::_;
Ben Chan190d3cf2011-07-07 09:38:48 -070033
Ben Chan460439f2011-09-13 09:16:28 -070034namespace {
Ben Chanf51ff002011-04-25 12:41:57 -070035
Ben Chan460439f2011-09-13 09:16:28 -070036const char kMountRootDirectory[] = "/media/removable";
37
38} // namespace
39
40namespace cros_disks {
Ben Chan8dcede82011-07-25 20:56:13 -070041
Ben Chan1e5a0cb2012-03-22 00:41:52 -070042// A mock device ejector class for testing the disk manager class.
43class MockDeviceEjector : public DeviceEjector {
44 public:
45 MockDeviceEjector() {}
46
47 MOCK_METHOD1(Eject, bool(const string& device_path));
48};
49
Ben Chanf51ff002011-04-25 12:41:57 -070050class DiskManagerTest : public ::testing::Test {
Ben Chan29be9152011-07-25 14:39:48 -070051 public:
Ben Chan8dcede82011-07-25 20:56:13 -070052 DiskManagerTest()
Ben Chan1e5a0cb2012-03-22 00:41:52 -070053 : manager_(kMountRootDirectory, &platform_, &metrics_, &device_ejector_) {
Ben Chan29be9152011-07-25 14:39:48 -070054 }
55
Ben Chane31d2aa2011-06-15 13:52:59 -070056 protected:
Ben Chanbe2b4a72011-11-08 13:42:23 -080057 Metrics metrics_;
Ben Chan29be9152011-07-25 14:39:48 -070058 Platform platform_;
Ben Chan1e5a0cb2012-03-22 00:41:52 -070059 MockDeviceEjector device_ejector_;
Ben Chane31d2aa2011-06-15 13:52:59 -070060 DiskManager manager_;
Ben Chanf51ff002011-04-25 12:41:57 -070061};
62
Ben Chanaf455a02013-01-08 15:29:22 -080063TEST_F(DiskManagerTest, CreateExFATMounter) {
64 Disk disk;
65 disk.set_device_file("/dev/sda1");
66
67 Filesystem filesystem("exfat");
68 filesystem.set_mounter_type(ExFATMounter::kMounterType);
69
70 string target_path = "/media/disk";
Ben Chan63ec9c42014-04-21 19:13:23 -070071 vector<string> options = {"rw", "nodev", "noexec", "nosuid"};
Ben Chanaf455a02013-01-08 15:29:22 -080072
Ben Chan5e3ca672014-08-25 15:53:58 -070073 unique_ptr<Mounter> mounter(
74 manager_.CreateMounter(disk, filesystem, target_path, options));
Ben Chan44e7ea62014-08-29 18:13:37 -070075 EXPECT_NE(nullptr, mounter.get());
Ben Chanaf455a02013-01-08 15:29:22 -080076 EXPECT_EQ(filesystem.mount_type(), mounter->filesystem_type());
77 EXPECT_EQ(disk.device_file(), mounter->source_path());
78 EXPECT_EQ(target_path, mounter->target_path());
Jorge Lucangeli Obesa4d01112013-02-11 21:28:16 -080079 EXPECT_EQ("rw,nodev,noexec,nosuid", mounter->mount_options().ToString());
Ben Chanaf455a02013-01-08 15:29:22 -080080}
81
Ben Chane31d2aa2011-06-15 13:52:59 -070082TEST_F(DiskManagerTest, CreateExternalMounter) {
83 Disk disk;
84 disk.set_device_file("/dev/sda1");
85
Ben Chanb1ac5a82011-08-02 17:53:55 -070086 Filesystem filesystem("fat");
87 filesystem.set_mount_type("vfat");
88 filesystem.set_mounter_type(ExternalMounter::kMounterType);
Ben Chane31d2aa2011-06-15 13:52:59 -070089
Ben Chan190d3cf2011-07-07 09:38:48 -070090 string target_path = "/media/disk";
Ben Chan63ec9c42014-04-21 19:13:23 -070091 vector<string> options = {"rw", "nodev", "noexec", "nosuid"};
Ben Chane31d2aa2011-06-15 13:52:59 -070092
Ben Chan5e3ca672014-08-25 15:53:58 -070093 unique_ptr<Mounter> mounter(
94 manager_.CreateMounter(disk, filesystem, target_path, options));
Ben Chan44e7ea62014-08-29 18:13:37 -070095 EXPECT_NE(nullptr, mounter.get());
Ben Chanb1ac5a82011-08-02 17:53:55 -070096 EXPECT_EQ(filesystem.mount_type(), mounter->filesystem_type());
97 EXPECT_EQ(disk.device_file(), mounter->source_path());
98 EXPECT_EQ(target_path, mounter->target_path());
Jorge Lucangeli Obesa4d01112013-02-11 21:28:16 -080099 EXPECT_EQ("rw,nodev,noexec,nosuid", mounter->mount_options().ToString());
Ben Chanb1ac5a82011-08-02 17:53:55 -0700100}
101
102TEST_F(DiskManagerTest, CreateNTFSMounter) {
103 Disk disk;
104 disk.set_device_file("/dev/sda1");
105
106 Filesystem filesystem("ntfs");
107 filesystem.set_mounter_type(NTFSMounter::kMounterType);
108
109 string target_path = "/media/disk";
Ben Chan63ec9c42014-04-21 19:13:23 -0700110 vector<string> options = {"rw", "nodev", "noexec", "nosuid"};
Ben Chanb1ac5a82011-08-02 17:53:55 -0700111
Ben Chan5e3ca672014-08-25 15:53:58 -0700112 unique_ptr<Mounter> mounter(
113 manager_.CreateMounter(disk, filesystem, target_path, options));
Ben Chan44e7ea62014-08-29 18:13:37 -0700114 EXPECT_NE(nullptr, mounter.get());
Ben Chane31d2aa2011-06-15 13:52:59 -0700115 EXPECT_EQ(filesystem.mount_type(), mounter->filesystem_type());
116 EXPECT_EQ(disk.device_file(), mounter->source_path());
117 EXPECT_EQ(target_path, mounter->target_path());
Jorge Lucangeli Obesa4d01112013-02-11 21:28:16 -0800118 EXPECT_EQ("rw,nodev,noexec,nosuid", mounter->mount_options().ToString());
Ben Chane31d2aa2011-06-15 13:52:59 -0700119}
120
121TEST_F(DiskManagerTest, CreateSystemMounter) {
122 Disk disk;
123 disk.set_device_file("/dev/sda1");
124
125 Filesystem filesystem("vfat");
Ben Chan1bea08e2011-06-27 16:59:09 -0700126 filesystem.AddExtraMountOption("utf8");
127 filesystem.AddExtraMountOption("shortname=mixed");
Ben Chane31d2aa2011-06-15 13:52:59 -0700128
Ben Chan190d3cf2011-07-07 09:38:48 -0700129 string target_path = "/media/disk";
Ben Chan63ec9c42014-04-21 19:13:23 -0700130 vector<string> options = {"rw", "nodev", "noexec", "nosuid"};
Ben Chane31d2aa2011-06-15 13:52:59 -0700131
Ben Chan5e3ca672014-08-25 15:53:58 -0700132 unique_ptr<Mounter> mounter(
133 manager_.CreateMounter(disk, filesystem, target_path, options));
Ben Chan44e7ea62014-08-29 18:13:37 -0700134 EXPECT_NE(nullptr, mounter.get());
Ben Chane31d2aa2011-06-15 13:52:59 -0700135 EXPECT_EQ(filesystem.mount_type(), mounter->filesystem_type());
136 EXPECT_EQ(disk.device_file(), mounter->source_path());
137 EXPECT_EQ(target_path, mounter->target_path());
Jorge Lucangeli Obesa4d01112013-02-11 21:28:16 -0800138 EXPECT_EQ("utf8,shortname=mixed,rw,nodev,noexec,nosuid",
Ben Chan8dcede82011-07-25 20:56:13 -0700139 mounter->mount_options().ToString());
Ben Chane31d2aa2011-06-15 13:52:59 -0700140}
141
Ben Chanf51ff002011-04-25 12:41:57 -0700142TEST_F(DiskManagerTest, EnumerateDisks) {
Ben Chan190d3cf2011-07-07 09:38:48 -0700143 vector<Disk> disks = manager_.EnumerateDisks();
Ben Chane31d2aa2011-06-15 13:52:59 -0700144}
145
Ben Chanf51ff002011-04-25 12:41:57 -0700146TEST_F(DiskManagerTest, GetDiskByDevicePath) {
Ben Chanf51ff002011-04-25 12:41:57 -0700147 Disk disk;
Ben Chan190d3cf2011-07-07 09:38:48 -0700148 string device_path = "/dev/sda";
Ben Chane31d2aa2011-06-15 13:52:59 -0700149 EXPECT_TRUE(manager_.GetDiskByDevicePath(device_path, &disk));
Ben Chanf51ff002011-04-25 12:41:57 -0700150 EXPECT_EQ(device_path, disk.device_file());
151
152 device_path = "/dev/sda1";
Ben Chane31d2aa2011-06-15 13:52:59 -0700153 EXPECT_TRUE(manager_.GetDiskByDevicePath(device_path, &disk));
Ben Chanf51ff002011-04-25 12:41:57 -0700154 EXPECT_EQ(device_path, disk.device_file());
155}
156
157TEST_F(DiskManagerTest, GetDiskByNonexistentDevicePath) {
Ben Chanf51ff002011-04-25 12:41:57 -0700158 Disk disk;
Ben Chan190d3cf2011-07-07 09:38:48 -0700159 string device_path = "/dev/nonexistent-path";
Ben Chane31d2aa2011-06-15 13:52:59 -0700160 EXPECT_FALSE(manager_.GetDiskByDevicePath(device_path, &disk));
Ben Chanf51ff002011-04-25 12:41:57 -0700161}
162
Ben Chanb092d752011-07-13 11:44:38 -0700163TEST_F(DiskManagerTest, GetFilesystem) {
Ben Chan44e7ea62014-08-29 18:13:37 -0700164 EXPECT_EQ(nullptr, manager_.GetFilesystem("nonexistent-fs"));
Ben Chanb092d752011-07-13 11:44:38 -0700165
166 Filesystem normal_fs("normal-fs");
Ben Chan44e7ea62014-08-29 18:13:37 -0700167 EXPECT_EQ(nullptr, manager_.GetFilesystem(normal_fs.type()));
Ben Chanb092d752011-07-13 11:44:38 -0700168 manager_.RegisterFilesystem(normal_fs);
Ben Chan44e7ea62014-08-29 18:13:37 -0700169 EXPECT_NE(nullptr, manager_.GetFilesystem(normal_fs.type()));
Ben Chanb092d752011-07-13 11:44:38 -0700170}
171
Ben Chane31d2aa2011-06-15 13:52:59 -0700172TEST_F(DiskManagerTest, RegisterFilesystem) {
Ben Chan190d3cf2011-07-07 09:38:48 -0700173 map<string, Filesystem>& filesystems = manager_.filesystems_;
Ben Chane31d2aa2011-06-15 13:52:59 -0700174 EXPECT_EQ(0, filesystems.size());
175 EXPECT_TRUE(filesystems.find("nonexistent") == filesystems.end());
176
177 Filesystem fat_fs("fat");
178 fat_fs.set_accepts_user_and_group_id(true);
179 manager_.RegisterFilesystem(fat_fs);
180 EXPECT_EQ(1, filesystems.size());
181 EXPECT_TRUE(filesystems.find(fat_fs.type()) != filesystems.end());
182
183 Filesystem vfat_fs("vfat");
184 vfat_fs.set_accepts_user_and_group_id(true);
185 manager_.RegisterFilesystem(vfat_fs);
186 EXPECT_EQ(2, filesystems.size());
187 EXPECT_TRUE(filesystems.find(vfat_fs.type()) != filesystems.end());
188}
189
Ben Chan8dcede82011-07-25 20:56:13 -0700190TEST_F(DiskManagerTest, CanMount) {
191 EXPECT_TRUE(manager_.CanMount("/dev/sda1"));
192 EXPECT_TRUE(manager_.CanMount("/devices/block/sda/sda1"));
193 EXPECT_TRUE(manager_.CanMount("/sys/devices/block/sda/sda1"));
194 EXPECT_FALSE(manager_.CanMount("/media/removable/disk1"));
195 EXPECT_FALSE(manager_.CanMount("/media/removable/disk1/"));
196 EXPECT_FALSE(manager_.CanMount("/media/removable/disk 1"));
197 EXPECT_FALSE(manager_.CanMount("/media/archive/test.zip"));
198 EXPECT_FALSE(manager_.CanMount("/media/archive/test.zip/"));
199 EXPECT_FALSE(manager_.CanMount("/media/archive/test 1.zip"));
200 EXPECT_FALSE(manager_.CanMount("/media/removable/disk1/test.zip"));
201 EXPECT_FALSE(manager_.CanMount("/media/removable/disk1/test 1.zip"));
202 EXPECT_FALSE(manager_.CanMount("/media/removable/disk1/dir1/test.zip"));
203 EXPECT_FALSE(manager_.CanMount("/media/removable/test.zip/test1.zip"));
204 EXPECT_FALSE(manager_.CanMount("/home/chronos/user/Downloads/test1.zip"));
Ben Chan16d85862013-05-28 20:30:30 -0700205 EXPECT_FALSE(manager_.CanMount("/home/chronos/user/GCache/test1.zip"));
206 EXPECT_FALSE(manager_.CanMount("/home/chronos"
207 "/u-0123456789abcdef0123456789abcdef01234567"
208 "/Downloads/test1.zip"));
209 EXPECT_FALSE(manager_.CanMount("/home/chronos"
210 "/u-0123456789abcdef0123456789abcdef01234567"
211 "/GCache/test1.zip"));
Ben Chan8dcede82011-07-25 20:56:13 -0700212 EXPECT_FALSE(manager_.CanMount(""));
213 EXPECT_FALSE(manager_.CanMount("/tmp"));
214 EXPECT_FALSE(manager_.CanMount("/media/removable"));
215 EXPECT_FALSE(manager_.CanMount("/media/removable/"));
216 EXPECT_FALSE(manager_.CanMount("/media/archive"));
217 EXPECT_FALSE(manager_.CanMount("/media/archive/"));
218 EXPECT_FALSE(manager_.CanMount("/home/chronos/user/Downloads"));
219 EXPECT_FALSE(manager_.CanMount("/home/chronos/user/Downloads/"));
Ben Chanf51ff002011-04-25 12:41:57 -0700220}
221
Ben Chan8dcede82011-07-25 20:56:13 -0700222TEST_F(DiskManagerTest, CanUnmount) {
223 EXPECT_TRUE(manager_.CanUnmount("/dev/sda1"));
224 EXPECT_TRUE(manager_.CanUnmount("/devices/block/sda/sda1"));
225 EXPECT_TRUE(manager_.CanUnmount("/sys/devices/block/sda/sda1"));
226 EXPECT_TRUE(manager_.CanUnmount("/media/removable/disk1"));
227 EXPECT_TRUE(manager_.CanUnmount("/media/removable/disk1/"));
228 EXPECT_TRUE(manager_.CanUnmount("/media/removable/disk 1"));
229 EXPECT_FALSE(manager_.CanUnmount("/media/archive/test.zip"));
230 EXPECT_FALSE(manager_.CanUnmount("/media/archive/test.zip/"));
231 EXPECT_FALSE(manager_.CanUnmount("/media/archive/test 1.zip"));
232 EXPECT_FALSE(manager_.CanUnmount("/media/removable/disk1/test.zip"));
233 EXPECT_FALSE(manager_.CanUnmount("/media/removable/disk1/test 1.zip"));
234 EXPECT_FALSE(manager_.CanUnmount("/media/removable/disk1/dir1/test.zip"));
235 EXPECT_FALSE(manager_.CanUnmount("/media/removable/test.zip/test1.zip"));
236 EXPECT_FALSE(manager_.CanUnmount("/home/chronos/user/Downloads/test1.zip"));
Ben Chan16d85862013-05-28 20:30:30 -0700237 EXPECT_FALSE(manager_.CanUnmount("/home/chronos/user/GCache/test1.zip"));
238 EXPECT_FALSE(manager_.CanUnmount("/home/chronos"
239 "/u-0123456789abcdef0123456789abcdef01234567"
240 "/Downloads/test1.zip"));
241 EXPECT_FALSE(manager_.CanUnmount("/home/chronos"
242 "/u-0123456789abcdef0123456789abcdef01234567"
243 "/GCache/test1.zip"));
Ben Chan8dcede82011-07-25 20:56:13 -0700244 EXPECT_FALSE(manager_.CanUnmount(""));
245 EXPECT_FALSE(manager_.CanUnmount("/tmp"));
246 EXPECT_FALSE(manager_.CanUnmount("/media/removable"));
247 EXPECT_FALSE(manager_.CanUnmount("/media/removable/"));
248 EXPECT_FALSE(manager_.CanUnmount("/media/archive"));
249 EXPECT_FALSE(manager_.CanUnmount("/media/archive/"));
250 EXPECT_FALSE(manager_.CanUnmount("/home/chronos/user/Downloads"));
251 EXPECT_FALSE(manager_.CanUnmount("/home/chronos/user/Downloads/"));
252}
253
254TEST_F(DiskManagerTest, DoMountDiskWithNonexistentSourcePath) {
255 string filesystem_type = "ext3";
256 string source_path = "/dev/nonexistent-path";
257 string mount_path = "/tmp/cros-disks-test";
Ben Chan190d3cf2011-07-07 09:38:48 -0700258 vector<string> options;
Ben Chanfcb2fc02011-11-21 09:44:07 -0800259 EXPECT_EQ(MOUNT_ERROR_INVALID_DEVICE_PATH,
Ben Chan8dcede82011-07-25 20:56:13 -0700260 manager_.DoMount(source_path, filesystem_type, options,
261 mount_path));
262}
263
264TEST_F(DiskManagerTest, DoUnmountDiskWithInvalidUnmountOptions) {
265 string source_path = "/dev/nonexistent-path";
Ben Chan63ec9c42014-04-21 19:13:23 -0700266 vector<string> options = {"invalid-unmount-option"};
Ben Chanfcb2fc02011-11-21 09:44:07 -0800267 EXPECT_EQ(MOUNT_ERROR_INVALID_UNMOUNT_OPTIONS,
Ben Chan8dcede82011-07-25 20:56:13 -0700268 manager_.DoUnmount(source_path, options));
Ben Chanf51ff002011-04-25 12:41:57 -0700269}
270
Ben Chanb5d71222012-10-03 12:55:16 -0700271TEST_F(DiskManagerTest, ScheduleEjectOnUnmount) {
272 string mount_path = "/media/removable/disk";
273 Disk disk;
274 disk.set_device_file("/dev/sr0");
275 EXPECT_FALSE(manager_.ScheduleEjectOnUnmount(mount_path, disk));
276 EXPECT_FALSE(ContainsKey(manager_.devices_to_eject_on_unmount_, mount_path));
277
278 disk.set_media_type(DEVICE_MEDIA_OPTICAL_DISC);
279 EXPECT_TRUE(manager_.ScheduleEjectOnUnmount(mount_path, disk));
280 EXPECT_TRUE(ContainsKey(manager_.devices_to_eject_on_unmount_, mount_path));
281
282 disk.set_media_type(DEVICE_MEDIA_DVD);
283 manager_.devices_to_eject_on_unmount_.clear();
284 EXPECT_TRUE(manager_.ScheduleEjectOnUnmount(mount_path, disk));
285 EXPECT_TRUE(ContainsKey(manager_.devices_to_eject_on_unmount_, mount_path));
Ben Chan1e5a0cb2012-03-22 00:41:52 -0700286}
287
Ben Chanb5d71222012-10-03 12:55:16 -0700288TEST_F(DiskManagerTest, EjectDeviceOfMountPath) {
289 string mount_path = "/media/removable/disk";
290 string device_file = "/dev/sr0";
291 manager_.devices_to_eject_on_unmount_[mount_path] = device_file;
292 EXPECT_CALL(device_ejector_, Eject(_)).WillOnce(Return(true));
293 EXPECT_TRUE(manager_.EjectDeviceOfMountPath(mount_path));
294 EXPECT_FALSE(ContainsKey(manager_.devices_to_eject_on_unmount_, mount_path));
295}
296
297TEST_F(DiskManagerTest, EjectDeviceOfMountPathWhenEjectFailed) {
298 string mount_path = "/media/removable/disk";
299 string device_file = "/dev/sr0";
300 manager_.devices_to_eject_on_unmount_[mount_path] = device_file;
301 EXPECT_CALL(device_ejector_, Eject(_)).WillOnce(Return(false));
302 EXPECT_FALSE(manager_.EjectDeviceOfMountPath(mount_path));
303 EXPECT_FALSE(ContainsKey(manager_.devices_to_eject_on_unmount_, mount_path));
304}
305
306TEST_F(DiskManagerTest, EjectDeviceOfMountPathWhenExplicitlyDisabled) {
307 string mount_path = "/media/removable/disk";
308 string device_file = "/dev/sr0";
309 manager_.devices_to_eject_on_unmount_[mount_path] = device_file;
310 manager_.eject_device_on_unmount_ = false;
Ben Chan1e5a0cb2012-03-22 00:41:52 -0700311 EXPECT_CALL(device_ejector_, Eject(_)).Times(0);
Ben Chanb5d71222012-10-03 12:55:16 -0700312 EXPECT_FALSE(manager_.EjectDeviceOfMountPath(mount_path));
313 EXPECT_FALSE(ContainsKey(manager_.devices_to_eject_on_unmount_, mount_path));
314}
315
316TEST_F(DiskManagerTest, EjectDeviceOfMountPathWhenMountPathExcluded) {
317 EXPECT_CALL(device_ejector_, Eject(_)).Times(0);
318 EXPECT_FALSE(manager_.EjectDeviceOfMountPath("/media/removable/disk"));
Ben Chan1e5a0cb2012-03-22 00:41:52 -0700319}
320
Ben Chanf51ff002011-04-25 12:41:57 -0700321} // namespace cros_disks