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

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: Cancel in UI thread, etc. 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];
sail 2013/01/26 02:11:38 camera_.reset([[MockMTPICCameraDevice alloc] init.
Greg Billock 2013/01/28 18:57:07 This camera object is owned in the manager. Change
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 delegate_->CancelPendingTasksAndDeleteDelegate();
182 }
183
184 protected:
185 MessageLoopForUI message_loop_;
186 scoped_ptr<content::TestBrowserThread> ui_thread_;
187 scoped_ptr<base::SystemMonitor> system_monitor_;
188 chrome::ImageCaptureDeviceManager manager_;
189 ICCameraDevice* camera_;
sail 2013/01/26 02:11:38 scoped_nsobject?
Greg Billock 2013/01/28 18:57:07 Commented this to better reflect ownerships.
190 scoped_refptr<base::SequencedTaskRunner> task_runner_;
191
192 // This object needs special deletion inside the above |task_runner_|.
193 chrome::MTPDeviceDelegateImplMac* delegate_;
194
195 private:
196 DISALLOW_COPY_AND_ASSIGN(MTPDeviceDelegateImplMacTest);
197 };
198
199 TEST_F(MTPDeviceDelegateImplMacTest, TestGetRootFileInfo) {
200 base::PlatformFileInfo info;
201 // Making a fresh delegate should have a single file entry for the synthetic
202 // root directory, with the name equal to the device id string.
203 EXPECT_EQ(base::PLATFORM_FILE_OK,
204 delegate_->GetFileInfo(FilePath("/ic:id"), &info));
205 EXPECT_TRUE(info.is_directory);
206 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
207 delegate_->GetFileInfo(FilePath("/nonexistent"), &info));
208
209 // Signal the delegate that no files are coming.
210 delegate_->NoMoreItems();
211
212 scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator> enumerator =
213 delegate_->CreateFileEnumerator(FilePath("/ic:id"), true);
214 EXPECT_TRUE(enumerator->Next().empty());
215 }
216
217 TEST_F(MTPDeviceDelegateImplMacTest, TestGetFileInfo) {
218 base::Time time1 = base::Time::Now();
219 base::PlatformFileInfo info1;
220 info1.size = 1;
221 info1.is_directory = false;
222 info1.is_symbolic_link = false;
223 info1.last_modified = time1;
224 info1.last_accessed = time1;
225 info1.creation_time = time1;
226 delegate_->ItemAdded("name1", info1);
227
228 base::PlatformFileInfo info;
229 EXPECT_EQ(base::PLATFORM_FILE_OK,
230 delegate_->GetFileInfo(FilePath("/ic:id/name1"), &info));
231 EXPECT_EQ(info1.size, info.size);
232 EXPECT_EQ(info1.is_directory, info.is_directory);
233 EXPECT_EQ(info1.last_modified, info.last_modified);
234 EXPECT_EQ(info1.last_accessed, info.last_accessed);
235 EXPECT_EQ(info1.creation_time, info.creation_time);
236
237 info1.size = 2;
238 delegate_->ItemAdded("name2", info1);
239 delegate_->NoMoreItems();
240
241 EXPECT_EQ(base::PLATFORM_FILE_OK,
242 delegate_->GetFileInfo(FilePath("/ic:id/name2"), &info));
243 EXPECT_EQ(info1.size, info.size);
244
245 scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator> enumerator =
246 delegate_->CreateFileEnumerator(FilePath("/ic:id"), true);
247 FilePath next = enumerator->Next();
248 ASSERT_FALSE(next.empty());
249 EXPECT_EQ(1, enumerator->Size());
250 EXPECT_EQ(time1, enumerator->LastModifiedTime());
251 EXPECT_FALSE(enumerator->IsDirectory());
252 EXPECT_EQ("/ic:id/name1", next.value());
253
254 next = enumerator->Next();
255 ASSERT_FALSE(next.empty());
256 EXPECT_EQ(2, enumerator->Size());
257 EXPECT_EQ(time1, enumerator->LastModifiedTime());
258 EXPECT_FALSE(enumerator->IsDirectory());
259 EXPECT_EQ("/ic:id/name2", next.value());
260
261 next = enumerator->Next();
262 EXPECT_TRUE(next.empty());
263 }
264
265 TEST_F(MTPDeviceDelegateImplMacTest, TestIgnoreDirectories) {
266 base::Time time1 = base::Time::Now();
267 base::PlatformFileInfo info1;
268 info1.size = 1;
269 info1.is_directory = false;
270 info1.is_symbolic_link = false;
271 info1.last_modified = time1;
272 info1.last_accessed = time1;
273 info1.creation_time = time1;
274 delegate_->ItemAdded("name1", info1);
275
276 info1.is_directory = true;
277 delegate_->ItemAdded("dir1", info1);
278 delegate_->ItemAdded("dir2", info1);
279
280 info1.is_directory = false;
281 delegate_->ItemAdded("name2", info1);
282 delegate_->NoMoreItems();
283
284 scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator> enumerator =
285 delegate_->CreateFileEnumerator(FilePath("/ic:id"), true);
286 FilePath next = enumerator->Next();
287 ASSERT_FALSE(next.empty());
288 EXPECT_EQ("/ic:id/name1", next.value());
289
290 next = enumerator->Next();
291 ASSERT_FALSE(next.empty());
292 EXPECT_EQ("/ic:id/name2", next.value());
293
294 next = enumerator->Next();
295 EXPECT_TRUE(next.empty());
296 }
297
298 TEST_F(MTPDeviceDelegateImplMacTest, EnumeratorWaitsForEntries) {
299 base::Time time1 = base::Time::Now();
300 base::PlatformFileInfo info1;
301 info1.size = 1;
302 info1.is_directory = false;
303 info1.is_symbolic_link = false;
304 info1.last_modified = time1;
305 info1.last_accessed = time1;
306 info1.creation_time = time1;
307 delegate_->ItemAdded("name1", info1);
308
309 scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator> enumerator =
310 delegate_->CreateFileEnumerator(FilePath("/ic:id"), true);
311 // Event is manually reset, initially unsignaled
312 base::WaitableEvent event(true, false);
313 FilePath next;
314 task_runner_->PostTask(FROM_HERE,
315 base::Bind(&EnumerateAndSignal,
316 enumerator.get(), &event, &next));
317 message_loop_.RunUntilIdle();
318 ASSERT_TRUE(event.IsSignaled());
319 EXPECT_EQ("/ic:id/name1", next.value());
320
321 event.Reset();
322
323 // This method will block until it is sure there are no more items.
324 task_runner_->PostTask(FROM_HERE,
325 base::Bind(&EnumerateAndSignal,
326 enumerator.get(), &event, &next));
327 message_loop_.RunUntilIdle();
328 ASSERT_FALSE(event.IsSignaled());
329 delegate_->NoMoreItems();
330 event.Wait();
331 ASSERT_TRUE(event.IsSignaled());
332 EXPECT_TRUE(next.empty());
333 message_loop_.RunUntilIdle();
334 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698