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

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

Powered by Google App Engine
This is Rietveld 408576698