OLD | NEW |
---|---|
(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 | |
6 #import <Foundation/Foundation.h> | |
7 #import <ImageCaptureCore/ImageCaptureCore.h> | |
8 | |
9 #include "base/file_path.h" | |
10 #include "base/file_util.h" | |
11 #include "base/files/scoped_temp_dir.h" | |
12 #include "base/mac/foundation_util.h" | |
13 #include "base/memory/weak_ptr.h" | |
14 #include "base/message_loop.h" | |
15 #include "base/system_monitor/system_monitor.h" | |
16 #include "chrome/browser/system_monitor/image_capture_device.h" | |
17 #include "chrome/browser/system_monitor/image_capture_device_manager.h" | |
18 #include "content/public/test/test_browser_thread.h" | |
19 #include "testing/gtest/include/gtest/gtest.h" | |
20 | |
21 namespace { | |
22 | |
23 const char kDeviceId[] = "id"; | |
24 const char kTestFileContents[] = "test"; | |
25 | |
26 } // namespace | |
27 | |
28 @interface MockICCameraDevice : ICCameraDevice { | |
29 @private | |
30 scoped_nsobject<NSMutableArray> allMediaFiles_; | |
31 } | |
32 | |
33 - (void)addMediaFile:(ICCameraFile*)file; | |
34 | |
35 @end | |
36 | |
37 @implementation MockICCameraDevice | |
38 | |
39 - (NSString*)mountPoint { | |
40 return @"mountPoint"; | |
41 } | |
42 | |
43 - (NSString*)name { | |
44 return @"name"; | |
45 } | |
46 | |
47 - (NSString*)UUIDString { | |
48 return base::SysUTF8ToNSString(kDeviceId); | |
49 } | |
50 | |
51 - (ICDeviceType)type { | |
52 return ICDeviceTypeCamera; | |
53 } | |
54 | |
55 - (void)requestOpenSession { | |
56 } | |
57 | |
58 - (void)requestCloseSession { | |
59 } | |
60 | |
61 - (NSArray*)mediaFiles { | |
62 return allMediaFiles_; | |
63 } | |
64 | |
65 - (void)addMediaFile:(ICCameraFile*)file { | |
66 if (!allMediaFiles_.get()) | |
67 allMediaFiles_.reset([NSMutableArray arrayWithCapacity:1]); | |
68 [allMediaFiles_ addObject:file]; | |
69 } | |
70 | |
71 // This method does approximately what the internal ImageCapture platform | |
72 // library is observed to do: take the download save-as filename and mangle | |
73 // it to attach an extension, then return that new filename to the caller | |
74 // in the options. | |
75 - (void)requestDownloadFile:(ICCameraFile*)file | |
76 options:(NSDictionary*)options | |
77 downloadDelegate:(id<ICCameraDeviceDownloadDelegate>)downloadDelegate | |
78 didDownloadSelector:(SEL)selector | |
79 contextInfo:(void*)contextInfo { | |
80 FilePath saveDir(base::SysNSStringToUTF8( | |
81 [[options objectForKey:ICDownloadsDirectoryURL] path])); | |
82 std::string saveAsFilename = | |
83 base::SysNSStringToUTF8([options objectForKey:ICSaveAsFilename]); | |
84 // It appears that the ImageCapture library adds an extension to the requested | |
85 // filename. Do that here to require a rename. | |
86 saveAsFilename += ".jpg"; | |
87 FilePath toBeSaved = saveDir.Append(saveAsFilename); | |
88 ASSERT_EQ(static_cast<int>(strlen(kTestFileContents)), | |
89 file_util::WriteFile(toBeSaved, kTestFileContents, | |
90 strlen(kTestFileContents))); | |
91 | |
92 NSMutableDictionary* returnOptions = | |
93 [NSMutableDictionary dictionaryWithDictionary:options]; | |
94 [returnOptions setObject:base::SysUTF8ToNSString(saveAsFilename) | |
95 forKey:ICSavedFilename]; | |
96 | |
97 [downloadDelegate didDownloadFile:file | |
98 error:nil | |
99 options:returnOptions | |
100 contextInfo:contextInfo]; | |
101 } | |
102 | |
103 @end | |
104 | |
105 @interface MockICCameraFile : ICCameraFile { | |
106 @private | |
107 scoped_nsobject<NSString> name_; | |
108 scoped_nsobject<NSDate> date_; | |
109 } | |
110 | |
111 - (id)init:(NSString*)name; | |
112 | |
113 @end | |
114 | |
115 @implementation MockICCameraFile | |
116 | |
117 - (id)init:(NSString*)name { | |
118 if ((self = [super init])) { | |
119 name_.reset([NSString stringWithString:name]); | |
120 date_.reset([[NSDate dateWithNaturalLanguageString:@"12/12/12"] retain]); | |
121 } | |
122 return self; | |
123 } | |
124 | |
125 - (NSString*)name { | |
126 return name_.get(); | |
127 } | |
128 | |
129 - (NSString*)UTI { | |
130 return base::mac::CFToNSCast(kUTTypeImage); | |
131 } | |
132 | |
133 - (NSDate*)modificationDate { | |
134 return date_.get(); | |
135 } | |
136 | |
137 - (NSDate*)creationDate { | |
138 return date_.get(); | |
139 } | |
140 | |
141 - (off_t)fileSize { | |
142 return 1000; | |
143 } | |
144 | |
145 @end | |
146 | |
147 class TestCameraListener | |
148 : public ImageCaptureDeviceListener, | |
149 public base::SupportsWeakPtr<TestCameraListener> { | |
150 public: | |
151 TestCameraListener() | |
152 : completed_(false), | |
153 removed_(false), | |
154 last_error_(base::PLATFORM_FILE_ERROR_INVALID_URL) {} | |
155 virtual ~TestCameraListener() {} | |
156 | |
157 virtual void ItemAdded(const std::string& name, | |
158 const base::PlatformFileInfo& info) OVERRIDE { | |
159 items_.push_back(name); | |
160 } | |
161 | |
162 virtual void NoMoreItems() OVERRIDE { | |
163 completed_ = true; | |
164 } | |
165 | |
166 virtual void DownloadedFile(const std::string& name, | |
167 base::PlatformFileError error) OVERRIDE { | |
168 EXPECT_TRUE(content::BrowserThread::CurrentlyOn( | |
169 content::BrowserThread::UI)); | |
170 downloads_.push_back(name); | |
171 last_error_ = error; | |
172 } | |
173 | |
174 virtual void DeviceRemoved() OVERRIDE { | |
175 removed_ = true; | |
176 } | |
177 | |
178 std::vector<std::string> items() { return items_; } | |
179 std::vector<std::string> downloads() { return downloads_; } | |
180 bool completed() { return completed_; } | |
181 bool removed() { return removed_; } | |
182 base::PlatformFileError last_error() { return last_error_; } | |
183 | |
184 private: | |
185 std::vector<std::string> items_; | |
186 std::vector<std::string> downloads_; | |
187 bool completed_; | |
188 bool removed_; | |
189 base::PlatformFileError last_error_; | |
190 }; | |
191 | |
192 class ImageCaptureDeviceManagerTest : public testing::Test { | |
193 public: | |
194 virtual void SetUp() OVERRIDE { | |
195 base::SystemMonitor::AllocateSystemIOPorts(); | |
196 system_monitor_.reset(new base::SystemMonitor()); | |
197 ui_thread_.reset(new content::TestBrowserThread( | |
198 content::BrowserThread::UI, &message_loop_)); | |
199 } | |
200 | |
201 MockICCameraDevice* AttachDevice( | |
202 chrome::ImageCaptureDeviceManager* manager) { | |
203 // Ownership will be passed to the device browser delegate. | |
204 MockICCameraDevice* device = [MockICCameraDevice alloc]; | |
205 id<ICDeviceBrowserDelegate> delegate = manager->device_browser(); | |
206 [delegate deviceBrowser:nil didAddDevice:device moreComing:NO]; | |
207 return device; | |
208 } | |
209 | |
210 void DetachDevice(chrome::ImageCaptureDeviceManager* manager, | |
211 ICCameraDevice* device) { | |
212 id<ICDeviceBrowserDelegate> delegate = manager->device_browser(); | |
213 [delegate deviceBrowser:nil didRemoveDevice:device moreGoing:NO]; | |
214 } | |
215 | |
216 protected: | |
217 MessageLoopForUI message_loop_; | |
218 scoped_ptr<content::TestBrowserThread> ui_thread_; | |
219 scoped_ptr<base::SystemMonitor> system_monitor_; | |
220 TestCameraListener listener_; | |
221 }; | |
222 | |
223 TEST_F(ImageCaptureDeviceManagerTest, TestAttachDetach) { | |
224 chrome::ImageCaptureDeviceManager manager; | |
225 ICCameraDevice* device = AttachDevice(&manager); | |
226 | |
227 std::vector<base::SystemMonitor::RemovableStorageInfo> devices = | |
228 system_monitor_->GetAttachedRemovableStorage(); | |
229 | |
230 ASSERT_EQ(1U, devices.size()); | |
231 EXPECT_EQ(std::string("ic:") + kDeviceId, devices[0].device_id); | |
232 | |
233 DetachDevice(&manager, device); | |
234 devices = system_monitor_->GetAttachedRemovableStorage(); | |
235 ASSERT_EQ(0U, devices.size()); | |
236 }; | |
237 | |
238 TEST_F(ImageCaptureDeviceManagerTest, OpenCamera) { | |
239 chrome::ImageCaptureDeviceManager manager; | |
240 ICCameraDevice* device = AttachDevice(&manager); | |
241 | |
242 EXPECT_FALSE(chrome::ImageCaptureDeviceManager::deviceForUUID( | |
243 "nonexistent")); | |
244 | |
245 scoped_nsobject<ImageCaptureDevice> camera( | |
246 [chrome::ImageCaptureDeviceManager::deviceForUUID(kDeviceId) | |
247 retain]); | |
248 | |
249 [camera setListener:listener_.AsWeakPtr()]; | |
250 [camera open]; | |
251 | |
252 scoped_nsobject<MockICCameraFile> picture1( | |
253 [[MockICCameraFile alloc] init:@"pic1"]); | |
254 [camera cameraDevice:nil didAddItem:picture1]; | |
255 scoped_nsobject<MockICCameraFile> picture2( | |
256 [[MockICCameraFile alloc] init:@"pic2"]); | |
257 [camera cameraDevice:nil didAddItem:picture2]; | |
258 ASSERT_EQ(2U, listener_.items().size()); | |
259 EXPECT_EQ("pic1", listener_.items()[0]); | |
260 EXPECT_EQ("pic2", listener_.items()[1]); | |
261 EXPECT_FALSE(listener_.completed()); | |
262 | |
263 [camera deviceDidBecomeReadyWithCompleteContentCatalog:nil]; | |
264 ASSERT_EQ(2U, listener_.items().size()); | |
265 EXPECT_TRUE(listener_.completed()); | |
266 | |
267 [camera close]; | |
268 DetachDevice(&manager, device); | |
269 EXPECT_FALSE(chrome::ImageCaptureDeviceManager::deviceForUUID( | |
270 kDeviceId)); | |
271 } | |
272 | |
273 TEST_F(ImageCaptureDeviceManagerTest, RemoveCamera) { | |
274 chrome::ImageCaptureDeviceManager manager; | |
275 ICCameraDevice* device = AttachDevice(&manager); | |
276 | |
277 scoped_nsobject<ImageCaptureDevice> camera( | |
278 [chrome::ImageCaptureDeviceManager::deviceForUUID(kDeviceId) | |
279 retain]); | |
280 | |
281 [camera setListener:listener_.AsWeakPtr()]; | |
282 [camera open]; | |
283 | |
284 [camera didRemoveDevice:device]; | |
285 EXPECT_TRUE(listener_.removed()); | |
286 } | |
287 | |
288 TEST_F(ImageCaptureDeviceManagerTest, DownloadFile) { | |
289 scoped_ptr<content::TestBrowserThread> file_thread_( | |
290 new content::TestBrowserThread( | |
sail
2013/01/03 21:50:28
this needs to be indented 2 more spaces (thus the
Greg Billock
2013/01/03 23:09:42
Done.
| |
291 content::BrowserThread::FILE, &message_loop_)); | |
292 | |
293 chrome::ImageCaptureDeviceManager manager; | |
294 MockICCameraDevice* device = AttachDevice(&manager); | |
295 | |
296 scoped_nsobject<ImageCaptureDevice> camera( | |
297 [chrome::ImageCaptureDeviceManager::deviceForUUID(kDeviceId) | |
298 retain]); | |
299 | |
300 [camera setListener:listener_.AsWeakPtr()]; | |
301 [camera open]; | |
302 | |
303 std::string kTestFileName("pic1"); | |
304 | |
305 scoped_nsobject<MockICCameraFile> picture1( | |
306 [[MockICCameraFile alloc] init:@"pic1"]); | |
sail
2013/01/03 21:50:28
this can be base::SysUTF8ToNSString(kTestFileName)
Greg Billock
2013/01/03 23:09:42
Done. But I think it ends up that using literals i
sail
2013/01/04 00:00:36
By using unique constants it's easier to track dow
Greg Billock
2013/01/04 16:26:10
I think this is fine the way it ended up; I just d
| |
307 [device addMediaFile:picture1]; | |
308 [camera cameraDevice:nil didAddItem:picture1]; | |
309 | |
310 base::ScopedTempDir temp_dir; | |
311 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
312 | |
313 EXPECT_EQ(0U, listener_.downloads().size()); | |
314 | |
315 FilePath temp_file = temp_dir.path().Append("tempfile"); | |
sail
2013/01/03 21:50:28
high level comments about what you're testing woul
Greg Billock
2013/01/03 23:09:42
Done.
| |
316 [camera downloadFile:std::string("nonexistent") localPath:temp_file]; | |
317 message_loop_.RunUntilIdle(); | |
318 ASSERT_EQ(1U, listener_.downloads().size()); | |
319 EXPECT_EQ("nonexistent", listener_.downloads()[0]); | |
320 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, listener_.last_error()); | |
321 | |
322 [camera downloadFile:kTestFileName localPath:temp_file]; | |
323 message_loop_.RunUntilIdle(); | |
324 | |
325 ASSERT_EQ(2U, listener_.downloads().size()); | |
326 EXPECT_EQ(kTestFileName, listener_.downloads()[1]); | |
327 ASSERT_EQ(base::PLATFORM_FILE_OK, listener_.last_error()); | |
328 char file_contents[5]; | |
329 ASSERT_EQ(4, file_util::ReadFile(temp_file, file_contents, | |
330 strlen(kTestFileContents))); | |
331 EXPECT_EQ(kTestFileContents, | |
332 std::string(file_contents, strlen(kTestFileContents))); | |
333 } | |
OLD | NEW |