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

Side by Side Diff: chrome/browser/media_gallery/mac/mtp_device_delegate_impl_mac_unittest.mm

Issue 11416089: [Media Galleries] Filesystem interface for Mac PTP/MTP devices using ImageCaptureCore (part 3) (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Add locking in delegate Created 7 years, 11 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
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 #import <Foundation/Foundation.h>
6 #import <ImageCaptureCore/ImageCaptureCore.h>
7
8 #include "base/file_util.h"
9 #include "base/mac/foundation_util.h"
10 #include "base/memory/scoped_nsobject.h"
11 #include "base/message_loop.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/sys_string_conversions.h"
14 #include "base/system_monitor/system_monitor.h"
15 #include "base/test/sequenced_worker_pool_owner.h"
16 #include "base/threading/sequenced_worker_pool.h"
17 #include "chrome/browser/media_gallery/mac/mtp_device_delegate_impl_mac.h"
18 #include "chrome/browser/system_monitor/image_capture_device_manager.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/test/test_browser_thread.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "webkit/fileapi/file_system_file_util.h"
23
24 namespace {
25
26 const char kDeviceId[] = "id";
27 const char kTestFileContents[] = "test";
28
29 } // namespace
30
31 @interface MockMTPICCameraDevice : ICCameraDevice {
32 @private
33 scoped_nsobject<NSMutableArray> allMediaFiles_;
34 }
35
36 - (void)addMediaFile:(ICCameraFile*)file;
37
38 @end
39
40 @implementation MockMTPICCameraDevice
41
42 - (NSString*)mountPoint {
43 return @"mountPoint";
44 }
45
46 - (NSString*)name {
47 return @"name";
48 }
49
50 - (NSString*)UUIDString {
51 return base::SysUTF8ToNSString(kDeviceId);
52 }
53
54 - (ICDeviceType)type {
55 return ICDeviceTypeCamera;
56 }
57
58 - (void)requestOpenSession {
59 }
60
61 - (void)requestCloseSession {
62 }
63
64 - (NSArray*)mediaFiles {
65 return allMediaFiles_;
66 }
67
68 - (void)addMediaFile:(ICCameraFile*)file {
69 if (!allMediaFiles_.get())
70 allMediaFiles_.reset([[NSMutableArray alloc] init]);
71 [allMediaFiles_ addObject:file];
72 }
73
74 - (void)requestDownloadFile:(ICCameraFile*)file
75 options:(NSDictionary*)options
76 downloadDelegate:(id<ICCameraDeviceDownloadDelegate>)downloadDelegate
77 didDownloadSelector:(SEL)selector
78 contextInfo:(void*)contextInfo {
79 FilePath saveDir(base::SysNSStringToUTF8(
80 [[options objectForKey:ICDownloadsDirectoryURL] path]));
81 std::string saveAsFilename =
82 base::SysNSStringToUTF8([options objectForKey:ICSaveAsFilename]);
83 // It appears that the ImageCapture library adds an extension to the requested
84 // filename. Do that here to require a rename.
85 saveAsFilename += ".jpg";
86 FilePath toBeSaved = saveDir.Append(saveAsFilename);
87 ASSERT_EQ(static_cast<int>(strlen(kTestFileContents)),
88 file_util::WriteFile(toBeSaved, kTestFileContents,
89 strlen(kTestFileContents)));
90
91 NSMutableDictionary* returnOptions =
92 [NSMutableDictionary dictionaryWithDictionary:options];
93 [returnOptions setObject:base::SysUTF8ToNSString(saveAsFilename)
94 forKey:ICSavedFilename];
95
96 [downloadDelegate didDownloadFile:file
97 error:nil
98 options:returnOptions
99 contextInfo:contextInfo];
100 }
101
102 @end
103
104 @interface MockMTPICCameraFile : ICCameraFile {
105 @private
106 scoped_nsobject<NSString> name_;
107 scoped_nsobject<NSDate> date_;
108 }
109
110 - (id)init:(NSString*)name;
111
112 @end
113
114 @implementation MockMTPICCameraFile
115
116 - (id)init:(NSString*)name {
117 if ((self = [super init])) {
118 name_.reset([name retain]);
119 date_.reset([[NSDate dateWithNaturalLanguageString:@"12/12/12"] retain]);
120 }
121 return self;
122 }
123
124 - (NSString*)name {
125 return name_.get();
126 }
127
128 - (NSString*)UTI {
129 return base::mac::CFToNSCast(kUTTypeImage);
130 }
131
132 - (NSDate*)modificationDate {
133 return date_.get();
134 }
135
136 - (NSDate*)creationDate {
137 return date_.get();
138 }
139
140 - (off_t)fileSize {
141 return 1000;
142 }
143
144 @end
145
146 // Advances the enumerator. When the method returns, signals the waiting
147 // event.
148 void EnumerateAndSignal(
149 fileapi::FileSystemFileUtil::AbstractFileEnumerator* enumerator,
150 base::WaitableEvent* event,
151 FilePath* path) {
152 *path = enumerator->Next();
153 event->Signal();
154 }
155
156 class MTPDeviceDelegateImplMacTest : public testing::Test {
157 public:
158 MTPDeviceDelegateImplMacTest() : camera_(NULL), delegate_(NULL) {}
159
160 virtual void SetUp() OVERRIDE {
161 base::SystemMonitor::AllocateSystemIOPorts();
162 system_monitor_.reset(new base::SystemMonitor());
163 ui_thread_.reset(new content::TestBrowserThread(
164 content::BrowserThread::UI, &message_loop_));
165
166 camera_ = [MockMTPICCameraDevice alloc];
167 id<ICDeviceBrowserDelegate> delegate = manager_.device_browser();
168 [delegate deviceBrowser:nil didAddDevice:camera_ moreComing:NO];
169
170 base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
171 task_runner_ = pool->GetSequencedTaskRunner(
172 pool->GetNamedSequenceToken("token-name"));
173 delegate_ = new chrome::MTPDeviceDelegateImplMac(
174 "id", "/ic:id", task_runner_.get());
175 }
176
177 virtual void TearDown() OVERRIDE {
178 id<ICDeviceBrowserDelegate> delegate = manager_.device_browser();
179 [delegate deviceBrowser:nil didRemoveDevice:camera_ moreGoing:NO];
180
181 task_runner_->PostTask(FROM_HERE,
182 base::Bind(&chrome::MTPDeviceDelegateImplMac::
183 CancelPendingTasksAndDeleteDelegate,
184 base::Unretained(delegate_)));
185 }
186
187 protected:
188 MessageLoopForUI message_loop_;
189 scoped_ptr<content::TestBrowserThread> ui_thread_;
190 scoped_ptr<base::SystemMonitor> system_monitor_;
191 chrome::ImageCaptureDeviceManager manager_;
192 ICCameraDevice* camera_;
193 scoped_refptr<base::SequencedTaskRunner> task_runner_;
194
195 // This object needs special deletion inside the above |task_runner_|.
196 chrome::MTPDeviceDelegateImplMac* delegate_;
197
198 private:
199 DISALLOW_COPY_AND_ASSIGN(MTPDeviceDelegateImplMacTest);
200 };
201
202 TEST_F(MTPDeviceDelegateImplMacTest, TestGetRootFileInfo) {
203 base::PlatformFileInfo info;
204 // Making a fresh delegate should have a single file entry for the synthetic
205 // root directory, with the name equal to the device id string.
206 EXPECT_EQ(base::PLATFORM_FILE_OK,
207 delegate_->GetFileInfo(FilePath("/ic:id"), &info));
208 EXPECT_TRUE(info.is_directory);
209 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
210 delegate_->GetFileInfo(FilePath("/nonexistent"), &info));
211
212 // Signal the delegate that no files are coming.
213 delegate_->NoMoreItems();
214
215 scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator> enumerator =
216 delegate_->CreateFileEnumerator(FilePath("/ic:id"), true);
217 EXPECT_TRUE(enumerator->Next().empty());
218 }
219
220 TEST_F(MTPDeviceDelegateImplMacTest, TestGetFileInfo) {
221 base::Time time1 = base::Time::Now();
222 base::PlatformFileInfo info1;
223 info1.size = 1;
224 info1.is_directory = false;
225 info1.is_symbolic_link = false;
226 info1.last_modified = time1;
227 info1.last_accessed = time1;
228 info1.creation_time = time1;
229 delegate_->ItemAdded("name1", info1);
230
231 base::PlatformFileInfo info;
232 EXPECT_EQ(base::PLATFORM_FILE_OK,
233 delegate_->GetFileInfo(FilePath("/ic:id/name1"), &info));
234 EXPECT_EQ(info1.size, info.size);
235 EXPECT_EQ(info1.is_directory, info.is_directory);
236 EXPECT_EQ(info1.last_modified, info.last_modified);
237 EXPECT_EQ(info1.last_accessed, info.last_accessed);
238 EXPECT_EQ(info1.creation_time, info.creation_time);
239
240 info1.size = 2;
241 delegate_->ItemAdded("name2", info1);
242 delegate_->NoMoreItems();
243
244 EXPECT_EQ(base::PLATFORM_FILE_OK,
245 delegate_->GetFileInfo(FilePath("/ic:id/name2"), &info));
246 EXPECT_EQ(info1.size, info.size);
247
248 scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator> enumerator =
249 delegate_->CreateFileEnumerator(FilePath("/ic:id"), true);
250 FilePath next = enumerator->Next();
251 ASSERT_FALSE(next.empty());
252 EXPECT_EQ(1, enumerator->Size());
253 EXPECT_EQ(time1, enumerator->LastModifiedTime());
254 EXPECT_FALSE(enumerator->IsDirectory());
255 EXPECT_EQ("/ic:id/name1", next.value());
256
257 next = enumerator->Next();
258 ASSERT_FALSE(next.empty());
259 EXPECT_EQ(2, enumerator->Size());
260 EXPECT_EQ(time1, enumerator->LastModifiedTime());
261 EXPECT_FALSE(enumerator->IsDirectory());
262 EXPECT_EQ("/ic:id/name2", next.value());
263
264 next = enumerator->Next();
265 EXPECT_TRUE(next.empty());
266 }
267
268 TEST_F(MTPDeviceDelegateImplMacTest, TestIgnoreDirectories) {
269 base::Time time1 = base::Time::Now();
270 base::PlatformFileInfo info1;
271 info1.size = 1;
272 info1.is_directory = false;
273 info1.is_symbolic_link = false;
274 info1.last_modified = time1;
275 info1.last_accessed = time1;
276 info1.creation_time = time1;
277 delegate_->ItemAdded("name1", info1);
278
279 info1.is_directory = true;
280 delegate_->ItemAdded("dir1", info1);
281 delegate_->ItemAdded("dir2", info1);
282
283 info1.is_directory = false;
284 delegate_->ItemAdded("name2", info1);
285 delegate_->NoMoreItems();
286
287 scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator> enumerator =
288 delegate_->CreateFileEnumerator(FilePath("/ic:id"), true);
289 FilePath next = enumerator->Next();
290 ASSERT_FALSE(next.empty());
291 EXPECT_EQ("/ic:id/name1", next.value());
292
293 next = enumerator->Next();
294 ASSERT_FALSE(next.empty());
295 EXPECT_EQ("/ic:id/name2", next.value());
296
297 next = enumerator->Next();
298 EXPECT_TRUE(next.empty());
299 }
300
301 TEST_F(MTPDeviceDelegateImplMacTest, EnumeratorWaitsForEntries) {
302 base::Time time1 = base::Time::Now();
303 base::PlatformFileInfo info1;
304 info1.size = 1;
305 info1.is_directory = false;
306 info1.is_symbolic_link = false;
307 info1.last_modified = time1;
308 info1.last_accessed = time1;
309 info1.creation_time = time1;
310 delegate_->ItemAdded("name1", info1);
311
312 scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator> enumerator =
313 delegate_->CreateFileEnumerator(FilePath("/ic:id"), true);
314 // Event is manually reset, initially unsignaled
315 base::WaitableEvent event(true, false);
316 FilePath next;
317 task_runner_->PostTask(FROM_HERE,
318 base::Bind(&EnumerateAndSignal,
319 enumerator.get(), &event, &next));
320 message_loop_.RunUntilIdle();
321 ASSERT_TRUE(event.IsSignaled());
322 EXPECT_EQ("/ic:id/name1", next.value());
323
324 event.Reset();
325
326 // This method will block until it is sure there are no more items.
327 task_runner_->PostTask(FROM_HERE,
328 base::Bind(&EnumerateAndSignal,
329 enumerator.get(), &event, &next));
330 message_loop_.RunUntilIdle();
331 ASSERT_FALSE(event.IsSignaled());
332 delegate_->NoMoreItems();
333 event.Wait();
334 ASSERT_TRUE(event.IsSignaled());
335 EXPECT_TRUE(next.empty());
336 message_loop_.RunUntilIdle();
337 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698