1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chromeos/disks/disk.h"
6
7 #include <stdint.h>
8
9 #include <string>
10 #include <utility>
11 #include <vector>
12
13 #include "chromeos/dbus/cros_disks_client.h"
14 #include "dbus/message.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/cros_system_api/dbus/service_constants.h"
17
18 namespace chromeos {
19 namespace disks {
20 namespace {
21
22 const char kDevicePath[] = "/sys/device/path";
23 const char kDeviceFile[] = "/dev/sdb1";
24 const char kMountPath1[] = "/media/removable/UNTITLED";
25 const char kMountPath2[] = "/media/removable/second_mount_path";
26 const char kDriveModel[] = "DriveModel";
27 const char kIdLabel[] = "UNTITLED";
28 const char kIdUuid[] = "XXXX-YYYY";
29 const char kStorageDevicePath[] =
30 "/sys/devices/pci0000:00/0000:00:14.0/usb2/2-8/2-8:1.0/host14/target14:0:0/"
31 "14:0:0:0";
32 const char kProductId[] = "1234";
33 const char kProductName[] = "Product Name";
34 const char kVendorId[] = "0000";
35 const char kVendorName[] = "Vendor Name";
36 const char kFileSystemType[] = "exfat";
37 const uint64_t kDeviceSize = 16005464064;
38 const uint32_t kDeviceMediaType = cros_disks::DEVICE_MEDIA_SD;
39
40 // Appends a boolean entry to a dictionary of type "a{sv}"
AppendBoolDictEntry(dbus::MessageWriter * array_writer,const std::string & key,bool value)41 void AppendBoolDictEntry(dbus::MessageWriter* array_writer,
42 const std::string& key,
43 bool value) {
44 dbus::MessageWriter entry_writer(nullptr);
45 array_writer->OpenDictEntry(&entry_writer);
46 entry_writer.AppendString(key);
47 entry_writer.AppendVariantOfBool(value);
48 array_writer->CloseContainer(&entry_writer);
49 }
50
51 // Appends a string entry to a dictionary of type "a{sv}"
AppendStringDictEntry(dbus::MessageWriter * array_writer,const std::string & key,const std::string & value)52 void AppendStringDictEntry(dbus::MessageWriter* array_writer,
53 const std::string& key,
54 const std::string& value) {
55 dbus::MessageWriter entry_writer(nullptr);
56 array_writer->OpenDictEntry(&entry_writer);
57 entry_writer.AppendString(key);
58 entry_writer.AppendVariantOfString(value);
59 array_writer->CloseContainer(&entry_writer);
60 }
61
62 // Appends a uint64 entry to a dictionary of type "a{sv}"
AppendUint64DictEntry(dbus::MessageWriter * array_writer,const std::string & key,uint64_t value)63 void AppendUint64DictEntry(dbus::MessageWriter* array_writer,
64 const std::string& key,
65 uint64_t value) {
66 dbus::MessageWriter entry_writer(nullptr);
67 array_writer->OpenDictEntry(&entry_writer);
68 entry_writer.AppendString(key);
69 entry_writer.AppendVariantOfUint64(value);
70 array_writer->CloseContainer(&entry_writer);
71 }
72
73 // Appends a uint32 entry to a dictionary of type "a{sv}"
AppendUint32DictEntry(dbus::MessageWriter * array_writer,const std::string & key,uint64_t value)74 void AppendUint32DictEntry(dbus::MessageWriter* array_writer,
75 const std::string& key,
76 uint64_t value) {
77 dbus::MessageWriter entry_writer(nullptr);
78 array_writer->OpenDictEntry(&entry_writer);
79 entry_writer.AppendString(key);
80 entry_writer.AppendVariantOfUint32(value);
81 array_writer->CloseContainer(&entry_writer);
82 }
83
AppendBasicProperties(dbus::MessageWriter * array_writer)84 void AppendBasicProperties(dbus::MessageWriter* array_writer) {
85 AppendStringDictEntry(array_writer, cros_disks::kDeviceFile, kDeviceFile);
86 AppendStringDictEntry(array_writer, cros_disks::kDriveModel, kDriveModel);
87 AppendStringDictEntry(array_writer, cros_disks::kIdLabel, kIdLabel);
88 AppendStringDictEntry(array_writer, cros_disks::kIdUuid, kIdUuid);
89 AppendStringDictEntry(array_writer, cros_disks::kStorageDevicePath,
90 kStorageDevicePath);
91 AppendStringDictEntry(array_writer, cros_disks::kProductId, kProductId);
92 AppendStringDictEntry(array_writer, cros_disks::kProductName, kProductName);
93 AppendStringDictEntry(array_writer, cros_disks::kVendorId, kVendorId);
94 AppendStringDictEntry(array_writer, cros_disks::kVendorName, kVendorName);
95 AppendStringDictEntry(array_writer, cros_disks::kFileSystemType,
96 kFileSystemType);
97 AppendUint64DictEntry(array_writer, cros_disks::kDeviceSize, kDeviceSize);
98 AppendUint32DictEntry(array_writer, cros_disks::kDeviceMediaType,
99 kDeviceMediaType);
100 }
101
102 // Builds a dbus reponse with a common set of fields.
BuildBasicDbusResponse()103 std::unique_ptr<dbus::Response> BuildBasicDbusResponse() {
104 std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
105 dbus::MessageWriter writer(response.get());
106 dbus::MessageWriter array_writer(nullptr);
107
108 writer.OpenArray("{sv}", &array_writer);
109 AppendBasicProperties(&array_writer);
110 writer.CloseContainer(&array_writer);
111
112 return response;
113 }
114
TEST(DiskTest,ConstructFromDiskInfo)115 TEST(DiskTest, ConstructFromDiskInfo) {
116 const char kBaseMountpath[] = "/base/mount/path";
117
118 std::unique_ptr<dbus::Response> response = BuildBasicDbusResponse();
119 DiskInfo disk_info(kDevicePath, response.get());
120 Disk disk(disk_info, false /* write_disabled_by_policy */, kBaseMountpath);
121
122 EXPECT_EQ(kDevicePath, disk.device_path());
123 EXPECT_EQ(kDeviceFile, disk.file_path());
124 EXPECT_EQ(kIdLabel, disk.device_label());
125 EXPECT_EQ(kDriveModel, disk.drive_label());
126 EXPECT_EQ(kVendorId, disk.vendor_id());
127 EXPECT_EQ(kVendorName, disk.vendor_name());
128 EXPECT_EQ(kProductId, disk.product_id());
129 EXPECT_EQ(kProductName, disk.product_name());
130 EXPECT_EQ(kIdUuid, disk.fs_uuid());
131 EXPECT_EQ(kDeviceSize, disk.total_size_in_bytes());
132 EXPECT_EQ(DEVICE_TYPE_SD, disk.device_type());
133 EXPECT_EQ(kStorageDevicePath, disk.storage_device_path());
134 EXPECT_EQ(kBaseMountpath, disk.base_mount_path());
135 EXPECT_FALSE(disk.is_parent());
136 EXPECT_FALSE(disk.is_read_only());
137 EXPECT_FALSE(disk.is_read_only_hardware());
138 EXPECT_FALSE(disk.has_media());
139 EXPECT_FALSE(disk.on_boot_device());
140 EXPECT_FALSE(disk.on_removable_device());
141 EXPECT_FALSE(disk.is_mounted());
142 EXPECT_FALSE(disk.IsStatefulPartition());
143 EXPECT_FALSE(disk.is_auto_mountable());
144 EXPECT_TRUE(disk.is_first_mount());
145
146 // Drives are hidden by default.
147 EXPECT_TRUE(disk.is_hidden());
148 }
149
BuildDiskWithProperty(const std::string & property,bool value)150 std::unique_ptr<Disk> BuildDiskWithProperty(const std::string& property,
151 bool value) {
152 std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
153 {
154 dbus::MessageWriter writer(response.get());
155 dbus::MessageWriter array_writer(nullptr);
156
157 writer.OpenArray("{sv}", &array_writer);
158 AppendBasicProperties(&array_writer);
159 AppendBoolDictEntry(&array_writer, property, value);
160 writer.CloseContainer(&array_writer);
161 }
162 DiskInfo disk_info(kDevicePath, response.get());
163 return std::make_unique<Disk>(disk_info, false, "");
164 }
165
TEST(DiskTest,ConstructFromDiskInfo_BoolProperties)166 TEST(DiskTest, ConstructFromDiskInfo_BoolProperties) {
167 {
168 auto disk = BuildDiskWithProperty(cros_disks::kDeviceIsDrive, true);
169 EXPECT_TRUE(disk->is_parent());
170 }
171 {
172 auto disk = BuildDiskWithProperty(cros_disks::kDeviceIsReadOnly, true);
173 EXPECT_TRUE(disk->is_read_only());
174 EXPECT_TRUE(disk->is_read_only_hardware());
175 }
176 {
177 auto disk =
178 BuildDiskWithProperty(cros_disks::kDeviceIsMediaAvailable, true);
179 EXPECT_TRUE(disk->has_media());
180 }
181 {
182 auto disk = BuildDiskWithProperty(cros_disks::kDeviceIsOnBootDevice, true);
183 EXPECT_TRUE(disk->on_boot_device());
184 }
185 {
186 auto disk =
187 BuildDiskWithProperty(cros_disks::kDeviceIsOnRemovableDevice, true);
188 EXPECT_TRUE(disk->on_removable_device());
189 }
190 {
191 auto disk = BuildDiskWithProperty(cros_disks::kIsAutoMountable, true);
192 EXPECT_TRUE(disk->is_auto_mountable());
193 }
194 }
195
TEST(DiskTest,ConstructFromDiskInfo_WriteDisabledByPolicy)196 TEST(DiskTest, ConstructFromDiskInfo_WriteDisabledByPolicy) {
197 std::unique_ptr<dbus::Response> response = BuildBasicDbusResponse();
198 DiskInfo disk_info(kDevicePath, response.get());
199 Disk disk(disk_info, true /* write_disabled_by_policy */, "");
200
201 EXPECT_TRUE(disk.is_read_only());
202 EXPECT_FALSE(disk.is_read_only_hardware());
203 }
204
TEST(DiskTest,ConstructFromDiskInfo_Mounted)205 TEST(DiskTest, ConstructFromDiskInfo_Mounted) {
206 std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
207 {
208 dbus::MessageWriter writer(response.get());
209 dbus::MessageWriter array_writer(nullptr);
210
211 writer.OpenArray("{sv}", &array_writer);
212 AppendBasicProperties(&array_writer);
213 {
214 std::vector<std::string> mounted_paths = {kMountPath1, kMountPath2};
215
216 dbus::MessageWriter entry_writer(nullptr);
217 array_writer.OpenDictEntry(&entry_writer);
218 entry_writer.AppendString(cros_disks::kDeviceMountPaths);
219 dbus::MessageWriter variant_writer(nullptr);
220 entry_writer.OpenVariant("as", &variant_writer);
221 variant_writer.AppendArrayOfStrings(mounted_paths);
222 entry_writer.CloseContainer(&variant_writer);
223 array_writer.CloseContainer(&entry_writer);
224 }
225 writer.CloseContainer(&array_writer);
226 }
227
228 DiskInfo disk_info(kDevicePath, response.get());
229 Disk disk(disk_info, false, "");
230
231 EXPECT_TRUE(disk.is_mounted());
232 EXPECT_EQ(kMountPath1, disk.mount_path());
233 }
234
TEST(DiskTest,SetMountPath)235 TEST(DiskTest, SetMountPath) {
236 std::unique_ptr<dbus::Response> response = BuildBasicDbusResponse();
237 DiskInfo disk_info(kDevicePath, response.get());
238 Disk disk(disk_info, false /* write_disabled_by_policy */, "");
239
240 EXPECT_EQ("", disk.mount_path());
241 EXPECT_EQ("", disk.base_mount_path());
242 EXPECT_FALSE(disk.is_mounted());
243
244 disk.SetMountPath(kMountPath1);
245 EXPECT_EQ(kMountPath1, disk.mount_path());
246 EXPECT_EQ(kMountPath1, disk.base_mount_path());
247 EXPECT_FALSE(disk.is_mounted());
248
249 disk.set_mounted(true);
250 EXPECT_TRUE(disk.is_mounted());
251 }
252
253 } // namespace
254 } // namespace disks
255 } // namespace chromeos
256