OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <fcntl.h> | 5 #include <fcntl.h> |
6 #include <mntent.h> | 6 #include <mntent.h> |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 #include <sys/stat.h> | 8 #include <sys/stat.h> |
9 #include <sys/types.h> | 9 #include <sys/types.h> |
10 | 10 |
ajl
2012/03/23 22:47:39
The style guide now prefers *not* to have an empty
Lei Zhang
2012/03/24 03:01:26
Done.
Lei Zhang
2012/04/09 23:19:30
Ah, I asked mmentovai@ about this. This is a recen
| |
11 #include <string> | 11 #include <string> |
12 | 12 |
13 #include "base/file_util.h" | 13 #include "base/file_util.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
16 #include "base/message_loop.h" | 16 #include "base/message_loop.h" |
17 #include "base/scoped_temp_dir.h" | 17 #include "base/scoped_temp_dir.h" |
18 #include "base/system_monitor/system_monitor.h" | 18 #include "base/system_monitor/system_monitor.h" |
19 #include "base/test/mock_devices_changed_observer.h" | 19 #include "base/test/mock_devices_changed_observer.h" |
20 #include "content/browser/browser_thread_impl.h" | 20 #include "content/browser/browser_thread_impl.h" |
21 #include "content/browser/media_device_notifications_linux.h" | 21 #include "content/browser/media_device_notifications_linux.h" |
ajl
2012/03/23 22:47:39
This actually needs to be the very first file incl
Lei Zhang
2012/03/24 03:01:26
Done.
| |
22 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
23 | 23 |
24 using testing::_; | 24 using testing::_; |
25 | 25 |
26 namespace { | 26 namespace { |
27 | 27 |
28 const char* kValidFS = "vfat"; | 28 const char* kValidFS = "vfat"; |
29 const char* kInvalidFS = "invalidfs"; | 29 const char* kInvalidFS = "invalidfs"; |
30 | 30 |
31 const char* kInvalidPath = "invalid path does not exist"; | 31 const char* kInvalidPath = "invalid path does not exist"; |
32 | 32 |
33 const char* kDevice1 = "d1"; | 33 const char* kDevice1 = "d1"; |
34 const char* kDevice2 = "d2"; | 34 const char* kDevice2 = "d2"; |
35 const char* kDevice3 = "d3"; | 35 const char* kDevice3 = "d3"; |
36 | 36 |
37 const char* kMountPointA = "mnt_a"; | 37 const char* kMountPointA = "mnt_a"; |
38 const char* kMountPointB = "mnt_b"; | 38 const char* kMountPointB = "mnt_b"; |
39 | 39 |
40 } // namespace | 40 } // namespace |
41 | 41 |
42 namespace content { | 42 namespace content { |
43 | 43 |
44 class MediaDeviceNotificationsLinuxTest : public testing::Test { | 44 class MediaDeviceNotificationsLinuxTest : public testing::Test { |
ajl
2012/03/23 22:47:39
Can you put this test code inside an anonymous nam
Lei Zhang
2012/03/24 03:01:26
Done.
| |
45 public: | 45 public: |
46 struct MtabTestData { | 46 struct MtabTestData { |
47 MtabTestData(const char* mount_device, | 47 MtabTestData(const char* mount_device, |
ajl
2012/03/23 22:47:39
It seems like it could make this code simpler and
Lei Zhang
2012/03/24 03:01:26
Done.
| |
48 const char* mount_point, | 48 const char* mount_point, |
49 const char* mount_type) | 49 const char* mount_type) |
50 : mount_device(mount_device), | 50 : mount_device(mount_device), |
51 mount_point(mount_point), | 51 mount_point(mount_point), |
52 mount_type(mount_type) { | 52 mount_type(mount_type) { |
53 } | 53 } |
54 | 54 |
55 const char* mount_device; | 55 const char* mount_device; |
56 const char* mount_point; | 56 const char* mount_point; |
57 const char* mount_type; | 57 const char* mount_type; |
58 }; | 58 }; |
59 | 59 |
60 MediaDeviceNotificationsLinuxTest() | 60 MediaDeviceNotificationsLinuxTest() |
61 : message_loop_(MessageLoop::TYPE_IO), | 61 : message_loop_(MessageLoop::TYPE_IO), |
62 file_thread_(BrowserThread::FILE, &message_loop_) { | 62 file_thread_(BrowserThread::FILE, &message_loop_) { |
63 system_monitor_.reset(new base::SystemMonitor()); | 63 system_monitor_.reset(new base::SystemMonitor()); |
ajl
2012/03/23 22:47:39
Why not do this in the initializer list, instead o
Lei Zhang
2012/03/24 03:01:26
It is indeed moot.
| |
64 } | 64 } |
65 virtual ~MediaDeviceNotificationsLinuxTest() {} | 65 virtual ~MediaDeviceNotificationsLinuxTest() {} |
66 | 66 |
67 protected: | 67 protected: |
68 virtual void SetUp() { | 68 virtual void SetUp() { |
69 mock_devices_changed_observer_.reset(new base::MockDevicesChangedObserver); | 69 mock_devices_changed_observer_.reset(new base::MockDevicesChangedObserver); |
70 system_monitor_->AddDevicesChangedObserver( | 70 system_monitor_->AddDevicesChangedObserver( |
71 mock_devices_changed_observer_.get()); | 71 mock_devices_changed_observer_.get()); |
72 | 72 |
73 // Create and set up a temp dir with files for the test. | 73 // Create and set up a temp dir with files for the test. |
74 ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); | 74 ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); |
75 FilePath test_dir = scoped_temp_dir_.path().AppendASCII("test_etc"); | 75 FilePath test_dir = scoped_temp_dir_.path().AppendASCII("test_etc"); |
76 ASSERT_TRUE(file_util::CreateDirectory(test_dir)); | 76 ASSERT_TRUE(file_util::CreateDirectory(test_dir)); |
77 mtab_file_ = test_dir.AppendASCII("test_mtab"); | 77 mtab_file_ = test_dir.AppendASCII("test_mtab"); |
78 struct MtabTestData initial_test_data[] = { | 78 struct MtabTestData initial_test_data[] = { |
ajl
2012/03/23 22:47:39
C++ does not require prepending 'struct' to the na
Lei Zhang
2012/03/24 03:01:26
Done.
| |
79 MtabTestData("dummydevice", "dummydir", kInvalidFS), | 79 MtabTestData("dummydevice", "dummydir", kInvalidFS), |
80 }; | 80 }; |
81 WriteToMtab(initial_test_data, arraysize(initial_test_data), true); | 81 WriteToMtab(initial_test_data, arraysize(initial_test_data), true); |
82 | 82 |
83 // Initialize the test subject. | 83 // Initialize the test subject. |
84 notifications_ = new MediaDeviceNotificationsLinux(mtab_file_); | 84 notifications_ = new MediaDeviceNotificationsLinux(mtab_file_); |
85 notifications_->Init(); | 85 notifications_->Init(); |
86 message_loop_.RunAllPending(); | 86 message_loop_.RunAllPending(); |
87 } | 87 } |
88 | 88 |
(...skipping 24 matching lines...) Expand all Loading... | |
113 return_path = return_path.AppendASCII(dir); | 113 return_path = return_path.AppendASCII(dir); |
114 FilePath path(return_path); | 114 FilePath path(return_path); |
115 if (with_dcim_dir) | 115 if (with_dcim_dir) |
116 path = path.AppendASCII("DCIM"); | 116 path = path.AppendASCII("DCIM"); |
117 if (!file_util::CreateDirectory(path)) | 117 if (!file_util::CreateDirectory(path)) |
118 return FilePath(); | 118 return FilePath(); |
119 return return_path; | 119 return return_path; |
120 } | 120 } |
121 | 121 |
122 base::MockDevicesChangedObserver& observer() { | 122 base::MockDevicesChangedObserver& observer() { |
123 return *mock_devices_changed_observer_.get(); | 123 return *mock_devices_changed_observer_.get(); |
ajl
2012/03/23 22:47:39
Is get() needed here? Most smart pointer classes
Lei Zhang
2012/03/24 03:01:26
No, it's not, and I've already removed it in the C
| |
124 } | 124 } |
125 | 125 |
126 private: | 126 private: |
127 // Write the test mtab data to |mtab_file_|. | 127 // Write the test mtab data to |mtab_file_|. |
128 // |data| is an array of mtab entries. | 128 // |data| is an array of mtab entries. |
129 // |data_size| is the array size of |data|. | 129 // |data_size| is the array size of |data|. |
130 // |overwrite| specifies whether to overwrite |mtab_file_|. | 130 // |overwrite| specifies whether to overwrite |mtab_file_|. |
131 void WriteToMtab(struct MtabTestData* data, | 131 void WriteToMtab(struct MtabTestData* data, |
ajl
2012/03/23 22:47:39
Can data be const? The style guide prefers variab
Lei Zhang
2012/03/24 03:01:26
Done.
| |
132 size_t data_size, | 132 size_t data_size, |
133 bool overwrite) { | 133 bool overwrite) { |
134 FILE* file = setmntent(mtab_file_.value().c_str(), overwrite ? "w" : "a"); | 134 FILE* file = setmntent(mtab_file_.value().c_str(), overwrite ? "w" : "a"); |
135 ASSERT_TRUE(file); | 135 ASSERT_TRUE(file); |
136 | 136 |
137 struct mntent entry; | 137 struct mntent entry; |
138 entry.mnt_opts = strdup("rw"); | 138 entry.mnt_opts = strdup("rw"); |
139 entry.mnt_freq = 0; | 139 entry.mnt_freq = 0; |
140 entry.mnt_passno = 0; | 140 entry.mnt_passno = 0; |
141 for (size_t i = 0; i < data_size; ++i) { | 141 for (size_t i = 0; i < data_size; ++i) { |
142 entry.mnt_fsname = strdup(data[i].mount_device); | 142 entry.mnt_fsname = strdup(data[i].mount_device); |
ajl
2012/03/23 22:47:39
Why does the string need to be copied here? Is th
Lei Zhang
2012/03/24 03:01:26
The mntent struct has char* for these fields, wher
| |
143 entry.mnt_dir = strdup(data[i].mount_point); | 143 entry.mnt_dir = strdup(data[i].mount_point); |
144 entry.mnt_type = strdup(data[i].mount_type); | 144 entry.mnt_type = strdup(data[i].mount_type); |
145 int add_result = addmntent(file, &entry); | 145 int add_result = addmntent(file, &entry); |
146 ASSERT_EQ(0, add_result); | 146 ASSERT_EQ(0, add_result); |
147 free(entry.mnt_fsname); | 147 free(entry.mnt_fsname); |
148 free(entry.mnt_dir); | 148 free(entry.mnt_dir); |
149 free(entry.mnt_type); | 149 free(entry.mnt_type); |
150 } | 150 } |
151 free(entry.mnt_opts); | 151 free(entry.mnt_opts); |
152 int end_result = endmntent(file); | 152 int end_result = endmntent(file); |
153 ASSERT_EQ(1, end_result); | 153 ASSERT_EQ(1, end_result); |
154 | 154 |
155 // Need to ensure data reaches disk so the FilePathWatcher fires in time. | 155 // Need to ensure data reaches disk so the FilePathWatcher fires in time. |
156 // Otherwise this will cause MediaDeviceNotificationsLinuxTest to be flaky. | 156 // Otherwise this will cause MediaDeviceNotificationsLinuxTest to be flaky. |
157 int fd = open(mtab_file_.value().c_str(), O_RDONLY); | 157 int fd = open(mtab_file_.value().c_str(), O_RDONLY); |
158 ASSERT_GE(fd, 0); | 158 ASSERT_GE(fd, 0); |
ajl
2012/03/23 22:47:39
Just FYI: the gunit assertion macros (I'm assuming
Lei Zhang
2012/03/24 03:01:26
I've been pretty good about the _EQ macros, but I
| |
159 | 159 |
160 int fsync_result = fsync(fd); | 160 int fsync_result = fsync(fd); |
ajl
2012/03/23 22:47:39
Are you sure this temporary is necessary? Sometim
Lei Zhang
2012/03/24 03:01:26
This particular instance got removed in the follow
| |
161 ASSERT_EQ(0, fsync_result); | 161 ASSERT_EQ(0, fsync_result); |
162 | 162 |
163 int close_result = close(fd); | 163 int close_result = close(fd); |
164 ASSERT_EQ(0, close_result); | 164 ASSERT_EQ(0, close_result); |
165 } | 165 } |
166 | 166 |
167 // The message loop and file thread to run tests on. | 167 // The message loop and file thread to run tests on. |
168 MessageLoop message_loop_; | 168 MessageLoop message_loop_; |
169 BrowserThreadImpl file_thread_; | 169 BrowserThreadImpl file_thread_; |
170 | 170 |
171 // SystemMonitor and DevicesChangedObserver to hook together to test. | 171 // SystemMonitor and DevicesChangedObserver to hook together to test. |
172 scoped_ptr<base::SystemMonitor> system_monitor_; | 172 scoped_ptr<base::SystemMonitor> system_monitor_; |
ajl
2012/03/23 22:47:39
Does this really need to be allocated on the heap,
Lei Zhang
2012/03/24 03:01:26
Done.
| |
173 scoped_ptr<base::MockDevicesChangedObserver> mock_devices_changed_observer_; | 173 scoped_ptr<base::MockDevicesChangedObserver> mock_devices_changed_observer_; |
174 | 174 |
175 // Temporary directory for created test data. | 175 // Temporary directory for created test data. |
176 ScopedTempDir scoped_temp_dir_; | 176 ScopedTempDir scoped_temp_dir_; |
177 // Path to the test mtab file. | 177 // Path to the test mtab file. |
178 FilePath mtab_file_; | 178 FilePath mtab_file_; |
179 | 179 |
180 scoped_refptr<MediaDeviceNotificationsLinux> notifications_; | 180 scoped_refptr<MediaDeviceNotificationsLinux> notifications_; |
181 | 181 |
182 DISALLOW_COPY_AND_ASSIGN(MediaDeviceNotificationsLinuxTest); | 182 DISALLOW_COPY_AND_ASSIGN(MediaDeviceNotificationsLinuxTest); |
183 }; | 183 }; |
184 | 184 |
185 TEST_F(MediaDeviceNotificationsLinuxTest, BasicAttachDetach) { | 185 TEST_F(MediaDeviceNotificationsLinuxTest, BasicAttachDetach) { |
ajl
2012/03/23 22:47:39
It would be helpful to readers if you added a shor
Lei Zhang
2012/03/24 03:01:26
Done.
| |
186 testing::Sequence mock_sequence; | 186 testing::Sequence mock_sequence; |
187 FilePath test_path = CreateMountPoint(kMountPointA, true); | 187 FilePath test_path = CreateMountPoint(kMountPointA, true); |
ajl
2012/03/23 22:47:39
When you pass literals like true as function argum
Lei Zhang
2012/03/24 03:01:26
It's a bit tedious to repeat the same comment for
| |
188 ASSERT_FALSE(test_path.empty()); | 188 ASSERT_FALSE(test_path.empty()); |
189 struct MtabTestData test_data[] = { | 189 struct MtabTestData test_data[] = { |
190 MtabTestData(kDevice1, kInvalidPath, kValidFS), | 190 MtabTestData(kDevice1, kInvalidPath, kValidFS), |
191 MtabTestData(kDevice2, test_path.value().c_str(), kValidFS), | 191 MtabTestData(kDevice2, test_path.value().c_str(), kValidFS), |
192 }; | 192 }; |
193 EXPECT_CALL(observer(), OnMediaDeviceAttached(0, kDevice2, test_path)) | 193 EXPECT_CALL(observer(), OnMediaDeviceAttached(0, kDevice2, test_path)) |
ajl
2012/03/23 22:47:39
Please add a comment explaining what this actually
Lei Zhang
2012/03/24 03:01:26
Done. The more complicated cases are already comme
| |
194 .InSequence(mock_sequence); | 194 .InSequence(mock_sequence); |
195 WriteToMtabAndRunLoop(test_data, arraysize(test_data), false); | 195 WriteToMtabAndRunLoop(test_data, arraysize(test_data), false); |
196 | 196 |
197 EXPECT_CALL(observer(), OnMediaDeviceDetached(0)).InSequence(mock_sequence); | 197 EXPECT_CALL(observer(), OnMediaDeviceDetached(0)).InSequence(mock_sequence); |
198 WriteToMtabAndRunLoop(NULL, 0, true); | 198 WriteToMtabAndRunLoop(NULL, 0, true); |
199 } | 199 } |
200 | 200 |
201 // Only mount points with DCIM directories are recognized. | 201 // Only mount points with DCIM directories are recognized. |
202 TEST_F(MediaDeviceNotificationsLinuxTest, DCIM) { | 202 TEST_F(MediaDeviceNotificationsLinuxTest, DCIM) { |
203 testing::Sequence mock_sequence; | 203 testing::Sequence mock_sequence; |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
326 .Times(1); | 326 .Times(1); |
327 WriteToMtabAndRunLoop(test_data2, arraysize(test_data2), false); | 327 WriteToMtabAndRunLoop(test_data2, arraysize(test_data2), false); |
328 | 328 |
329 // Detach all devices. | 329 // Detach all devices. |
330 EXPECT_CALL(observer(), OnMediaDeviceAttached(_, _, _)).Times(0); | 330 EXPECT_CALL(observer(), OnMediaDeviceAttached(_, _, _)).Times(0); |
331 EXPECT_CALL(observer(), OnMediaDeviceDetached(1)).Times(1); | 331 EXPECT_CALL(observer(), OnMediaDeviceDetached(1)).Times(1); |
332 WriteToMtabAndRunLoop(NULL, 0, true); | 332 WriteToMtabAndRunLoop(NULL, 0, true); |
333 } | 333 } |
334 | 334 |
335 } // namespace content | 335 } // namespace content |
336 | |
OLD | NEW |