Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Side by Side Diff: content/browser/media_device_notifications_linux_unittest.cc

Issue 9560008: Implement Linux media notifier. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: with tests Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include <mntent.h>
6 #include <stdio.h>
7
8 #include <string>
9
10 #include "base/file_util.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop.h"
14 #include "base/scoped_temp_dir.h"
15 #include "base/system_monitor/system_monitor.h"
16 #include "content/browser/browser_thread_impl.h"
17 #include "content/browser/media_device_notifications_linux.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace {
21
22 const char* kValidFS = "vfat";
23 const char* kInvalidFS = "invalidfs";
24
25 const char* kInvalidPath = "invalid path does not exist";
26
27 const char* kDevice1 = "d1";
28 const char* kDevice2 = "d2";
29
30 const char* kMountPointA = "mnt_a";
31 const char* kMountPointB = "mnt_b";
32
33 } // namespace
34
35 namespace content {
36
37 class MediaDeviceNotificationsLinuxTest : public testing::Test {
38 public:
39 struct MtabTestData {
40 MtabTestData(const char* mount_device,
41 const char* mount_point,
42 const char* mount_type)
43 : mount_device(mount_device),
44 mount_point(mount_point),
45 mount_type(mount_type) {
46 }
47
48 const char* mount_device;
49 const char* mount_point;
50 const char* mount_type;
51 };
52
53 class DummyDeviceChangeObserver
54 : public base::SystemMonitor::DevicesChangedObserver {
55 public:
56 DummyDeviceChangeObserver()
57 : attach_count_(0),
58 detach_count_(0) {
59 }
60 virtual ~DummyDeviceChangeObserver() {}
61
62 void Reset() {
63 attach_count_ = 0;
64 detach_count_ = 0;
65 }
66
67 int attach_count() { return attach_count_; }
68 int detach_count() { return detach_count_; }
69
70 // base::SystemMonitor::DevicesChangedObserver implementation.
71 virtual void OnMediaDeviceAttached(
72 const base::SystemMonitor::DeviceIdType& id,
73 const std::string& name,
74 const FilePath& path) OVERRIDE {
75 ++attach_count_;
76 }
77 virtual void OnMediaDeviceDetached(
78 const base::SystemMonitor::DeviceIdType& id) OVERRIDE {
79 ++detach_count_;
80 }
81
82 private:
83 int attach_count_;
84 int detach_count_;
85
86 DISALLOW_COPY_AND_ASSIGN(DummyDeviceChangeObserver);
87 };
88
89 MediaDeviceNotificationsLinuxTest()
90 : message_loop_(MessageLoop::TYPE_IO),
91 file_thread_(BrowserThread::FILE, &message_loop_) {
92 system_monitor_.reset(new base::SystemMonitor());
93 system_monitor_->AddDevicesChangedObserver(&dummy_device_change_observer_);
94 }
95 virtual ~MediaDeviceNotificationsLinuxTest() {}
96
97 protected:
98 virtual void SetUp() {
99 dummy_device_change_observer_.Reset();
100
101 // Create and set up a temp dir with files for the test.
102 ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
103 FilePath test_dir = scoped_temp_dir_.path().AppendASCII("etc");
104 ASSERT_TRUE(file_util::CreateDirectory(test_dir));
105 mtab_file_ = test_dir.AppendASCII("foo");
106 struct MtabTestData initial_test_data[] = {
107 MtabTestData("dummydevice", "dummydir", kInvalidFS),
108 };
109 WriteToMtab(initial_test_data, arraysize(initial_test_data), true);
110
111 // Initialize the test subject.
112 notifications_ = new MediaDeviceNotificationsLinux(mtab_file_);
113 BrowserThread::PostTask(
114 BrowserThread::FILE, FROM_HERE,
115 base::Bind(&MediaDeviceNotificationsLinux::InitOnFileThread,
116 notifications_.get()));
117 message_loop_.RunAllPending();
118 }
119
120 virtual void TearDown() {
121 message_loop_.RunAllPending();
122 notifications_ = NULL;
123 ASSERT_TRUE(scoped_temp_dir_.Delete());
124 }
125
126 // Used to run tests. When the mtab file gets modified, the message loop
127 // needs to run in order to react to the file modification.
128 // See WriteToMtab for parameters.
129 void WriteToMtabAndRunLoop(struct MtabTestData* data,
130 size_t data_size,
131 bool overwrite) {
132 WriteToMtab(data, data_size, overwrite);
133 message_loop_.RunAllPending();
134 }
135
136 // Create a directory named |dir| relative to the test directory.
137 // Set |with_dcim_dir| to true if the created directory will have a "DCIM"
138 // subdirectory.
139 // Returns the full path to the created directory on success, or an empty
140 // path on failure.
141 FilePath CreateMountPoint(const char* dir, bool with_dcim_dir) {
142 FilePath return_path(scoped_temp_dir_.path());
143 return_path = return_path.AppendASCII(dir);
144 FilePath path(return_path);
145 if (with_dcim_dir)
146 path = path.AppendASCII("DCIM");
147 if (!file_util::CreateDirectory(path))
148 return FilePath();
149 return return_path;
150 }
151
152 int attach_count() { return dummy_device_change_observer_.attach_count(); }
153 int detach_count() { return dummy_device_change_observer_.detach_count(); }
154
155 private:
156 // Write the test mtab data to |mtab_file_|.
157 // |data| is an array of mtab entries.
158 // |data_size| is the array size of |data|.
159 // |overwrite| specifies whether to overwrite |mtab_file_|.
160 void WriteToMtab(struct MtabTestData* data,
161 size_t data_size,
162 bool overwrite) {
163 FILE* fd = setmntent(mtab_file_.value().c_str(), overwrite ? "w" : "a");
164 ASSERT_TRUE(fd);
165
166 scoped_ptr<char> mnt_opts(strdup("rw"));
167 struct mntent entry;
168 entry.mnt_opts = mnt_opts.get();
169 entry.mnt_freq = 0;
170 entry.mnt_passno = 0;
171 for (size_t i = 0; i < data_size; ++i) {
172 scoped_ptr<char> mnt_fsname(strdup(data[i].mount_device));
173 scoped_ptr<char> mnt_dir(strdup(data[i].mount_point));
174 scoped_ptr<char> mnt_type(strdup(data[i].mount_type));
175 entry.mnt_fsname = mnt_fsname.get();
176 entry.mnt_dir = mnt_dir.get();
177 entry.mnt_type = mnt_type.get();
178 int add_result = addmntent(fd, &entry);
179 ASSERT_EQ(0, add_result);
180 }
181 int end_result = endmntent(fd);
182 ASSERT_EQ(1, end_result);
183 }
184
185 // The message loop and file thread to run tests on.
186 MessageLoop message_loop_;
187 BrowserThreadImpl file_thread_;
188
189 // SystemMonitor and DevicesChangedObserver to hook together to test.
190 scoped_ptr<base::SystemMonitor> system_monitor_;
191 DummyDeviceChangeObserver dummy_device_change_observer_;
192
193 // Temporary directory for created test data.
194 ScopedTempDir scoped_temp_dir_;
195 // Path to the test mtab file.
196 FilePath mtab_file_;
197
198 scoped_refptr<MediaDeviceNotificationsLinux> notifications_;
199
200 DISALLOW_COPY_AND_ASSIGN(MediaDeviceNotificationsLinuxTest);
201 };
202
203 TEST_F(MediaDeviceNotificationsLinuxTest, BasicAttachDetach) {
204 FilePath test_path = CreateMountPoint(kMountPointA, true);
205 ASSERT_FALSE(test_path.empty());
206 struct MtabTestData test_data[] = {
207 MtabTestData(kDevice1, kInvalidPath, kValidFS),
208 MtabTestData(kDevice2, test_path.value().c_str(), kValidFS),
209 };
210 WriteToMtabAndRunLoop(test_data, arraysize(test_data), false);
211 EXPECT_EQ(1, attach_count());
212 EXPECT_EQ(0, detach_count());
213
214 WriteToMtabAndRunLoop(NULL, 0, true);
215 EXPECT_EQ(1, attach_count());
216 EXPECT_EQ(1, detach_count());
217 }
218
219 // Only mount points with DCIM directories are recognized.
220 TEST_F(MediaDeviceNotificationsLinuxTest, DCIM) {
221 FilePath test_path1 = CreateMountPoint(kMountPointA, true);
222 ASSERT_FALSE(test_path1.empty());
223 struct MtabTestData test_data1[] = {
224 MtabTestData(kDevice1, test_path1.value().c_str(), kValidFS),
225 };
226 WriteToMtabAndRunLoop(test_data1, arraysize(test_data1), false);
227 EXPECT_EQ(1, attach_count());
228 EXPECT_EQ(0, detach_count());
229
230 FilePath test_path2 = CreateMountPoint(kMountPointB, false);
231 ASSERT_FALSE(test_path2.empty());
232 struct MtabTestData test_data2[] = {
233 MtabTestData(kDevice2, test_path2.value().c_str(), kValidFS),
234 };
235 WriteToMtabAndRunLoop(test_data2, arraysize(test_data2), false);
236 EXPECT_EQ(1, attach_count());
237 EXPECT_EQ(0, detach_count());
238
239 WriteToMtabAndRunLoop(NULL, 0, true);
240 EXPECT_EQ(1, attach_count());
241 EXPECT_EQ(1, detach_count());
242 }
243
244 TEST_F(MediaDeviceNotificationsLinuxTest, MultiDeviceMultiMount) {
245 FilePath test_path1 = CreateMountPoint(kMountPointA, true);
246 FilePath test_path2 = CreateMountPoint(kMountPointB, true);
247 ASSERT_FALSE(test_path1.empty());
248 ASSERT_FALSE(test_path2.empty());
249 struct MtabTestData test_data1[] = {
250 MtabTestData(kDevice1, test_path1.value().c_str(), kValidFS),
251 MtabTestData(kDevice2, test_path2.value().c_str(), kValidFS),
252 };
253 WriteToMtabAndRunLoop(test_data1, arraysize(test_data1), false);
254 EXPECT_EQ(2, attach_count());
255 EXPECT_EQ(0, detach_count());
256
257 struct MtabTestData test_data2[] = {
258 MtabTestData(kDevice1, test_path2.value().c_str(), kValidFS),
259 MtabTestData(kDevice2, test_path1.value().c_str(), kValidFS),
260 };
261 WriteToMtabAndRunLoop(test_data2, arraysize(test_data2), false);
262 EXPECT_EQ(4, attach_count());
263 EXPECT_EQ(0, detach_count());
264
265 struct MtabTestData test_data3[] = {
266 MtabTestData(kDevice1, test_path1.value().c_str(), kValidFS),
267 MtabTestData(kDevice2, test_path2.value().c_str(), kValidFS),
268 MtabTestData(kDevice1, test_path2.value().c_str(), kValidFS),
269 };
270 WriteToMtabAndRunLoop(test_data3, arraysize(test_data3), true);
271 EXPECT_EQ(4, attach_count());
272 EXPECT_EQ(1, detach_count());
273
274 WriteToMtabAndRunLoop(test_data1, arraysize(test_data1), true);
275 EXPECT_EQ(4, attach_count());
276 EXPECT_EQ(2, detach_count());
277
278 WriteToMtabAndRunLoop(NULL, 0, true);
279 EXPECT_EQ(4, attach_count());
280 EXPECT_EQ(4, detach_count());
281 }
282
283 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698