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

Side by Side Diff: ios/chrome/browser/snapshots/snapshot_cache_unittest.mm

Issue 862693003: Upstream //ios/chrome/browser/snapshots (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 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 2012 The Chromium Authors. All rights reserved.
Paweł Hajdan Jr. 2015/01/30 12:24:29 nit: 2015
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 "ios/chrome/browser/snapshots/snapshot_cache.h"
6
7 #import <Foundation/Foundation.h>
8
9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h"
11 #include "base/format_macros.h"
12 #include "base/location.h"
13 #include "base/mac/bind_objc_block.h"
14 #include "base/mac/scoped_nsautorelease_pool.h"
15 #include "base/strings/sys_string_conversions.h"
16 #import "base/test/ios/wait_util.h"
17 #include "base/time/time.h"
18 #include "ios/chrome/browser/ui/ui_util.h"
19 #include "ios/web/public/test/test_web_thread.h"
20 #include "ios/web/public/web_thread.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "testing/gtest_mac.h"
23 #include "testing/platform_test.h"
24
25 static const NSUInteger kSessionCount = 10;
26 static const NSUInteger kSnapshotPixelSize = 8;
27
28 // Promote some implementation methods to public.
29 @interface SnapshotCache (Testing)
30 - (base::FilePath)imagePathForSessionID:(NSString*)sessionID;
31 - (base::FilePath)greyImagePathForSessionID:(NSString*)sessionID;
32 - (void)handleLowMemory;
33 @end
34
35 @interface SnapshotCache (TestingAdditions)
36 - (void)flushOperationQueue;
37 - (BOOL)hasImageInMemory:(NSString*)sessionID;
38 - (BOOL)hasGreyImageInMemory:(NSString*)sessionID;
39 @end
40
41 @implementation SnapshotCache (TestingAdditions)
42 - (void)flushOperationQueue {
43 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
44 web::WebThread::PostBlockingPoolSequencedTask(
45 "SnapshotCacheSequenceToken", FROM_HERE,
46 base::BindBlock(^{
47 dispatch_semaphore_signal(semaphore);
48 }));
49 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
50 dispatch_release(semaphore);
51 }
52 - (BOOL)hasImageInMemory:(NSString*)sessionID {
53 return [imageDictionary_ objectForKey:sessionID] != nil;
54 }
55 - (BOOL)hasGreyImageInMemory:(NSString*)sessionID {
56 return [greyImageDictionary_ objectForKey:sessionID] != nil;
57 }
58 @end
59
60 namespace {
61
62 class SnapshotCacheTest : public PlatformTest {
63 protected:
64 // Build an array of session names and an array of UIImages filled with
65 // random colors.
66 void SetUp() override {
67 file_thread_.reset(new web::TestWebThread(web::WebThread::FILE));
68 file_thread_->Start();
69 testImages_.reset([[NSMutableArray alloc] initWithCapacity:kSessionCount]);
70 testSessions_.reset(
71 [[NSMutableArray alloc] initWithCapacity:kSessionCount]);
72
73 CGFloat scale = [SnapshotCache snapshotScaleForDevice];
74 UIGraphicsBeginImageContextWithOptions(
75 CGSizeMake(kSnapshotPixelSize, kSnapshotPixelSize), NO, scale);
76 CGContextRef context = UIGraphicsGetCurrentContext();
77 srand(1);
78
79 for (NSUInteger i = 0; i < kSessionCount; ++i) {
80 UIImage* image = GenerateRandomImage(context);
81 [testImages_ addObject:image];
82 [testSessions_
83 addObject:[NSString stringWithFormat:@"SessionId-%" PRIuNS, i]];
84 }
85
86 UIGraphicsEndImageContext();
87 }
88
89 // Generates an image filled with a random color.
90 UIImage* GenerateRandomImage(CGContextRef context) {
91 CGFloat r = rand() / CGFloat(RAND_MAX);
92 CGFloat g = rand() / CGFloat(RAND_MAX);
93 CGFloat b = rand() / CGFloat(RAND_MAX);
94 CGContextSetRGBStrokeColor(context, r, g, b, 1.0);
95 CGContextSetRGBFillColor(context, r, g, b, 1.0);
96 CGContextFillRect(
97 context, CGRectMake(0.0, 0.0, kSnapshotPixelSize, kSnapshotPixelSize));
98 return UIGraphicsGetImageFromCurrentImageContext();
99 }
100
101 // This function removes the snapshots both from dictionary and from disk.
102 void ClearDumpedImages() {
103 SnapshotCache* cache = [SnapshotCache sharedInstance];
104
105 NSString* sessionID;
106 for (sessionID in testSessions_.get())
107 [cache removeImageWithSessionID:sessionID];
108
109 [cache flushOperationQueue];
110 // The above calls to -removeImageWithSessionID remove both the color
111 // and grey snapshots for each sessionID, if they are on disk. However,
112 // ensure we also get rid of the grey snapshots in memory.
113 [cache removeGreyCache];
114
115 __block BOOL foundImage = NO;
116 __block NSUInteger numCallbacks = 0;
117 for (sessionID in testSessions_.get()) {
118 base::FilePath path([cache imagePathForSessionID:sessionID]);
119
120 // Checks that the snapshot is not on disk.
121 EXPECT_FALSE(base::PathExists(path));
122
123 // Check that the snapshot is not in the dictionary.
124 [cache retrieveImageForSessionID:sessionID
125 callback:^(UIImage* image) {
126 numCallbacks++;
127 if (image)
128 foundImage = YES;
129 }];
130 }
131
132 // Spin the main message loop until all of the callbacks run. Time out
133 // after a while to avoid waiting forever.
134 NSUInteger expectedNumCallbacks = [testSessions_ count];
135 NSTimeInterval kTimeoutSec = 3;
Paweł Hajdan Jr. 2015/01/30 12:24:29 I strongly second Nico's comment about using base/
136 base::WaitUntilCondition(^bool() {
137 return numCallbacks >= expectedNumCallbacks;
138 }, nullptr, base::TimeDelta::FromSecondsD(kTimeoutSec));
139
140 // Expect that all the callbacks ran and that none retrieved an image.
141 EXPECT_EQ(expectedNumCallbacks, numCallbacks);
142 EXPECT_FALSE(foundImage);
143 }
144
145 // Loads kSessionCount color images into the cache. If |waitForFilesOnDisk|
146 // is YES, will not return until the images have been written to disk.
147 void LoadAllColorImagesIntoCache(bool waitForFilesOnDisk) {
148 LoadColorImagesIntoCache(kSessionCount, waitForFilesOnDisk);
149 }
150
151 // Loads |count| color images into the cache. If |waitForFilesOnDisk|
152 // is YES, will not return until the images have been written to disk.
153 void LoadColorImagesIntoCache(NSUInteger count, bool waitForFilesOnDisk) {
154 SnapshotCache* cache = [SnapshotCache sharedInstance];
155 // Put color images in the cache.
156 for (NSUInteger i = 0; i < count; ++i) {
157 base::mac::ScopedNSAutoreleasePool pool;
158 UIImage* image = [testImages_ objectAtIndex:i];
159 NSString* sessionID = [testSessions_ objectAtIndex:i];
160 [cache setImage:image withSessionID:sessionID];
161 }
162 if (waitForFilesOnDisk) {
163 [cache flushOperationQueue];
164 for (NSUInteger i = 0; i < count; ++i) {
165 // Check that images are on the disk.
166 NSString* sessionID = [testSessions_ objectAtIndex:i];
167 base::FilePath path([cache imagePathForSessionID:sessionID]);
168 EXPECT_TRUE(base::PathExists(path));
169 }
170 }
171 }
172
173 // Waits for the grey images for the sessions in |testSessions_| to be written
174 // to disk, which happens in a background thread.
175 void WaitForAllGreyImagesOnDisk() {
176 SnapshotCache* cache = [SnapshotCache sharedInstance];
177 NSString* sessionID;
178 NSTimeInterval kTimeoutSec = 3;
179 for (sessionID in testSessions_.get()) {
180 base::FilePath path([cache greyImagePathForSessionID:sessionID]);
181 base::WaitUntilCondition(^bool() {
182 return base::PathExists(path);
183 }, nullptr, base::TimeDelta::FromSecondsD(kTimeoutSec));
184 }
185 }
186
187 // Waits for the first |count| grey images for sessions in |testSessions_|
188 // to be placed in the cache.
189 void WaitForGreyImagesInCache(NSUInteger count) {
190 SnapshotCache* cache = [SnapshotCache sharedInstance];
191 NSTimeInterval kTimeoutSec = 3;
192 for (NSUInteger i = 0; i < count; i++) {
193 base::WaitUntilCondition(^bool() {
194 return [cache hasGreyImageInMemory:testSessions_[i]];
195 }, nullptr, base::TimeDelta::FromSecondsD(kTimeoutSec));
196 }
197 }
198
199 // Guesses the order of the color channels in the image.
200 // Supports RGB, BGR, RGBA, BGRA, ARGB, ABGR.
201 // Returns the position of each channel between 0 and 3.
202 void ComputeColorComponents(CGImageRef cgImage,
203 int* red,
204 int* green,
205 int* blue) {
206 CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(cgImage);
207 CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(cgImage);
208 int byteOrder = bitmapInfo & kCGBitmapByteOrderMask;
209
210 *red = 0;
211 *green = 1;
212 *blue = 2;
213
214 if (alphaInfo == kCGImageAlphaLast ||
215 alphaInfo == kCGImageAlphaPremultipliedLast ||
216 alphaInfo == kCGImageAlphaNoneSkipLast) {
217 *red = 1;
218 *green = 2;
219 *blue = 3;
220 }
221
222 if (byteOrder != kCGBitmapByteOrder32Host) {
223 int lastChannel = (CGImageGetBitsPerPixel(cgImage) == 24) ? 2 : 3;
224 *red = lastChannel - *red;
225 *green = lastChannel - *green;
226 *blue = lastChannel - *blue;
227 }
228 }
229
230 const char* GetPixelData(CGImageRef cgImage) {
231 CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(cgImage));
232 return reinterpret_cast<const char*>(CFDataGetBytePtr(data));
233 }
234
235 base::scoped_nsobject<NSMutableArray> testSessions_;
236 base::scoped_nsobject<NSMutableArray> testImages_;
237 scoped_ptr<web::TestWebThread> file_thread_;
238 };
239
240 // This test simply put all the snapshots in the cache and then gets them back
241 // As the snapshots are kept in memory, the same pointer can be retrieved.
242 // This test also checks that images are correctly removed from the disk.
243 TEST_F(SnapshotCacheTest, Cache) {
244 // Don't run on tablets because color snapshots are not cached so this test
245 // can't compare the UIImage pointers directly.
246 if (IsIPadIdiom()) {
247 return;
248 }
249
250 ClearDumpedImages();
251
252 SnapshotCache* cache = [SnapshotCache sharedInstance];
253
254 // Put all images in the cache.
255 for (NSUInteger i = 0; i < kSessionCount; ++i) {
256 UIImage* image = [testImages_ objectAtIndex:i];
257 NSString* sessionID = [testSessions_ objectAtIndex:i];
258 [cache setImage:image withSessionID:sessionID];
259 }
260
261 // Get images back.
262 __block NSUInteger numberOfCallbacks = 0;
263 for (NSUInteger i = 0; i < kSessionCount; ++i) {
264 NSString* sessionID = [testSessions_ objectAtIndex:i];
265 UIImage* expectedImage = [testImages_ objectAtIndex:i];
266 EXPECT_TRUE(expectedImage != nil);
267 [cache retrieveImageForSessionID:sessionID
268 callback:^(UIImage* image) {
269 // Images have not been removed from the
270 // dictionnary. We expect the same pointer.
271 EXPECT_EQ(expectedImage, image);
272 ++numberOfCallbacks;
273 }];
274 }
275 EXPECT_EQ(kSessionCount, numberOfCallbacks);
276
277 ClearDumpedImages();
278 }
279
280 // This test puts all the snapshots in the cache and flushes them to disk.
281 // The snapshots are then reloaded from the disk, and the colors are compared.
282 TEST_F(SnapshotCacheTest, SaveToDisk) {
283 ClearDumpedImages();
284
285 SnapshotCache* cache = [SnapshotCache sharedInstance];
286
287 // Put all images in the cache.
288 for (NSUInteger i = 0; i < kSessionCount; ++i) {
289 UIImage* image = [testImages_ objectAtIndex:i];
290 NSString* sessionID = [testSessions_ objectAtIndex:i];
291 [cache setImage:image withSessionID:sessionID];
292 }
293 [cache flushOperationQueue];
294
295 for (NSUInteger i = 0; i < kSessionCount; ++i) {
296 // Check that images are on the disk.
297 NSString* sessionID = [testSessions_ objectAtIndex:i];
298
299 base::FilePath path([cache imagePathForSessionID:sessionID]);
300 EXPECT_TRUE(base::PathExists(path));
301
302 // Check image colors by comparing the first pixel against the reference
303 // image.
304 UIImage* image =
305 [UIImage imageWithContentsOfFile:base::SysUTF8ToNSString(path.value())];
306 CGImageRef cgImage = [image CGImage];
307 const char* pixels = GetPixelData(cgImage);
308 EXPECT_TRUE(pixels);
309
310 UIImage* referenceImage = [testImages_ objectAtIndex:i];
311 CGImageRef referenceCgImage = [referenceImage CGImage];
312 const char* referencePixels = GetPixelData(referenceCgImage);
313 EXPECT_TRUE(referencePixels);
314
315 if (pixels != nil && referencePixels != nil) {
316 // Color components may not be in the same order,
317 // because of writing to disk and reloading.
318 int red, green, blue;
319 ComputeColorComponents(cgImage, &red, &green, &blue);
320
321 int referenceRed, referenceGreen, referenceBlue;
322 ComputeColorComponents(referenceCgImage, &referenceRed, &referenceGreen,
323 &referenceBlue);
324
325 // Colors may not be exactly the same (compression or rounding errors)
326 // thus a small difference is allowed.
327 EXPECT_NEAR(referencePixels[referenceRed], pixels[red], 1);
328 EXPECT_NEAR(referencePixels[referenceGreen], pixels[green], 1);
329 EXPECT_NEAR(referencePixels[referenceBlue], pixels[blue], 1);
330 }
331 }
332
333 ClearDumpedImages();
334 }
335
336 TEST_F(SnapshotCacheTest, PurgeTest) {
337 ClearDumpedImages();
338
339 SnapshotCache* cache = [SnapshotCache sharedInstance];
340
341 // Put all images in the cache.
342 for (NSUInteger i = 0; i < kSessionCount; ++i) {
343 UIImage* image = [testImages_ objectAtIndex:i];
344 NSString* sessionID = [testSessions_ objectAtIndex:i];
345 [cache setImage:image withSessionID:sessionID];
346 }
347
348 NSMutableSet* liveSessions = [NSMutableSet setWithCapacity:1];
349 [liveSessions addObject:[testSessions_ objectAtIndex:0]];
350
351 // Purge the cache.
352 [cache purgeCacheOlderThan:(base::Time::Now() - base::TimeDelta::FromHours(1))
353 keeping:liveSessions];
354 [cache flushOperationQueue];
355
356 // Check that nothing has been deleted.
357 for (NSUInteger i = 0; i < kSessionCount; ++i) {
358 // Check that images are on the disk.
359 NSString* sessionID = [testSessions_ objectAtIndex:i];
360
361 base::FilePath path([cache imagePathForSessionID:sessionID]);
362 EXPECT_TRUE(base::PathExists(path));
363 }
364
365 // Purge the cache.
366 [cache purgeCacheOlderThan:base::Time::Now() keeping:liveSessions];
367 [cache flushOperationQueue];
368
369 // Check that the file have been deleted.
370 for (NSUInteger i = 0; i < kSessionCount; ++i) {
371 // Check that images are on the disk.
372 NSString* sessionID = [testSessions_ objectAtIndex:i];
373
374 base::FilePath path([cache imagePathForSessionID:sessionID]);
375 if (i == 0)
376 EXPECT_TRUE(base::PathExists(path));
377 else
378 EXPECT_FALSE(base::PathExists(path));
379 }
380 ClearDumpedImages();
381 }
382
383 // Loads the color images into the cache, and pins two of them. Ensures that
384 // only the two pinned IDs remain in memory after a call to -handleLowMemory.
385 TEST_F(SnapshotCacheTest, testHandleLowMemory) {
386 ClearDumpedImages();
387 LoadAllColorImagesIntoCache(true);
388
389 SnapshotCache* cache = [SnapshotCache sharedInstance];
390
391 NSString* firstPinnedID = [testSessions_ objectAtIndex:4];
392 NSString* secondPinnedID = [testSessions_ objectAtIndex:6];
393 NSMutableSet* set = [NSMutableSet set];
394 [set addObject:firstPinnedID];
395 [set addObject:secondPinnedID];
396 cache.pinnedIDs = set;
397
398 [cache handleLowMemory];
399
400 BOOL expectedValue = YES;
401 if (IsIPadIdiom()) {
402 expectedValue = NO;
403 }
404 EXPECT_EQ(expectedValue, [cache hasImageInMemory:firstPinnedID]);
405 EXPECT_EQ(expectedValue, [cache hasImageInMemory:secondPinnedID]);
406
407 NSString* notPinnedID = [testSessions_ objectAtIndex:2];
408 EXPECT_FALSE([cache hasImageInMemory:notPinnedID]);
409
410 // Wait for the final image to be pulled off disk.
411 [cache flushOperationQueue];
412 ClearDumpedImages();
413 }
414
415 // Tests that createGreyCache creates the grey snapshots in the background,
416 // from color images in the in-memory cache. When the grey images are all
417 // loaded into memory, tests that the request to retrieve the grey snapshot
418 // calls the callback immediately.
419 // Disabled on simulators because it sometimes crashes. crbug/421425
420 #if !TARGET_IPHONE_SIMULATOR
421 TEST_F(SnapshotCacheTest, testCreateGreyCache) {
422 ClearDumpedImages();
423 LoadAllColorImagesIntoCache(true);
424
425 // Request the creation of a grey image cache for all images.
426 SnapshotCache* cache = [SnapshotCache sharedInstance];
427 [cache createGreyCache:testSessions_];
428
429 // Wait for them to be put into the grey image cache.
430 WaitForGreyImagesInCache(kSessionCount);
431
432 __block NSUInteger numberOfCallbacks = 0;
433 for (NSUInteger i = 0; i < kSessionCount; ++i) {
434 NSString* sessionID = [testSessions_ objectAtIndex:i];
435 [cache retrieveGreyImageForSessionID:sessionID
436 callback:^(UIImage* image) {
437 EXPECT_TRUE(image);
438 ++numberOfCallbacks;
439 }];
440 }
441
442 EXPECT_EQ(numberOfCallbacks, kSessionCount);
443 ClearDumpedImages();
444 }
445
446 // Same as previous test, except that all the color images are on disk,
447 // rather than in memory.
448 // Disabled due to the greyImage crash. b/8048597
449 TEST_F(SnapshotCacheTest, testCreateGreyCacheFromDisk) {
450 ClearDumpedImages();
451 LoadAllColorImagesIntoCache(true);
452
453 // Remove color images from in-memory cache.
454 SnapshotCache* cache = [SnapshotCache sharedInstance];
455 [cache handleLowMemory];
456
457 // Request the creation of a grey image cache for all images.
458 [cache createGreyCache:testSessions_];
459
460 // Wait for them to be put into the grey image cache.
461 WaitForGreyImagesInCache(kSessionCount);
462
463 __block NSUInteger numberOfCallbacks = 0;
464 for (NSUInteger i = 0; i < kSessionCount; ++i) {
465 NSString* sessionID = [testSessions_ objectAtIndex:i];
466 [cache retrieveGreyImageForSessionID:sessionID
467 callback:^(UIImage* image) {
468 EXPECT_TRUE(image);
469 ++numberOfCallbacks;
470 }];
471 }
472
473 EXPECT_EQ(numberOfCallbacks, kSessionCount);
474 ClearDumpedImages();
475 }
476 #endif // !TARGET_IPHONE_SIMULATOR
477
478 // Tests mostRecentGreyBlock, which is a block to be called when the most
479 // recently requested grey image is finally loaded.
480 // The test requests three images be cached as grey images. Only the final
481 // callback of the three requests should be called.
482 // Disabled due to the greyImage crash. b/8048597
483 TEST_F(SnapshotCacheTest, testMostRecentGreyBlock) {
484 ClearDumpedImages();
485
486 const NSUInteger kNumImages = 3;
487 base::scoped_nsobject<NSMutableArray> sessionIDs(
488 [[NSMutableArray alloc] initWithCapacity:kNumImages]);
489 [sessionIDs addObject:[testSessions_ objectAtIndex:0]];
490 [sessionIDs addObject:[testSessions_ objectAtIndex:1]];
491 [sessionIDs addObject:[testSessions_ objectAtIndex:2]];
492
493 SnapshotCache* cache = [SnapshotCache sharedInstance];
494
495 // Put 3 images in the cache.
496 LoadColorImagesIntoCache(kNumImages, true);
497 // Make sure the color images are only on disk, to ensure the background
498 // thread is slow enough to queue up the requests.
499 [cache handleLowMemory];
500
501 // Enable the grey image cache.
502 [cache createGreyCache:sessionIDs];
503
504 // Request the grey versions
505 __block BOOL firstCallbackCalled = NO;
506 __block BOOL secondCallbackCalled = NO;
507 __block BOOL thirdCallbackCalled = NO;
508 [cache greyImageForSessionID:[testSessions_ objectAtIndex:0]
509 callback:^(UIImage*) {
510 firstCallbackCalled = YES;
511 }];
512 [cache greyImageForSessionID:[testSessions_ objectAtIndex:1]
513 callback:^(UIImage*) {
514 secondCallbackCalled = YES;
515 }];
516 [cache greyImageForSessionID:[testSessions_ objectAtIndex:2]
517 callback:^(UIImage*) {
518 thirdCallbackCalled = YES;
519 }];
520
521 // Wait for them to be loaded.
522 WaitForGreyImagesInCache(kNumImages);
523
524 EXPECT_FALSE(firstCallbackCalled);
525 EXPECT_FALSE(secondCallbackCalled);
526 EXPECT_TRUE(thirdCallbackCalled);
527
528 ClearDumpedImages();
529 }
530
531 // Test the function used to save a grey copy of a color snapshot fully on a
532 // background thread when the application is backgrounded.
533 // Disabled due to the greyImage crash. b/8048597
534 TEST_F(SnapshotCacheTest, testGreyImageAllInBackground) {
535 ClearDumpedImages();
536 LoadAllColorImagesIntoCache(true);
537
538 SnapshotCache* cache = [SnapshotCache sharedInstance];
539
540 // Now convert every image into a grey image, on disk, in the background.
541 for (NSUInteger i = 0; i < kSessionCount; ++i) {
542 [cache saveGreyInBackgroundForSessionID:[testSessions_ objectAtIndex:i]];
543 }
544
545 WaitForAllGreyImagesOnDisk();
546
547 for (NSUInteger i = 0; i < kSessionCount; ++i) {
548 base::FilePath greyImagePath(
549 [cache greyImagePathForSessionID:[testSessions_ objectAtIndex:i]]);
550 EXPECT_TRUE(base::PathExists(greyImagePath));
551 base::DeleteFile(greyImagePath, false);
552 }
553
554 ClearDumpedImages();
555 }
556
557 // Verifies that image size and scale are preserved when writing and reading
558 // from disk.
559 TEST_F(SnapshotCacheTest, TestSizeAndScalePreservation) {
560 // Create an image with the expected snapshot scale.
561 CGFloat scale = [SnapshotCache snapshotScaleForDevice];
562 UIGraphicsBeginImageContextWithOptions(
563 CGSizeMake(kSnapshotPixelSize, kSnapshotPixelSize), NO, scale);
564 CGContextRef context = UIGraphicsGetCurrentContext();
565 UIImage* image = GenerateRandomImage(context);
566 UIGraphicsEndImageContext();
567
568 // Add the image to the cache then call handle low memory to ensure the image
569 // is read from disk instead of the in-memory cache.
570 SnapshotCache* cache = [SnapshotCache sharedInstance];
571 NSString* const kSession = @"foo";
572 [cache setImage:image withSessionID:kSession];
573 [cache flushOperationQueue]; // ensure the file is written to disk.
574 [cache handleLowMemory];
575
576 // Retrive the image and have the callback verify the size and scale.
577 __block BOOL callbackComplete = NO;
578 [cache retrieveImageForSessionID:kSession
579 callback:^(UIImage* imageFromDisk) {
580 EXPECT_EQ(image.size.width,
581 imageFromDisk.size.width);
582 EXPECT_EQ(image.size.height,
583 imageFromDisk.size.height);
584 EXPECT_EQ(image.scale, imageFromDisk.scale);
585 callbackComplete = YES;
586 }];
587
588 // Spin the main message loop until the callback is run. Time out after a
589 // a while to avoid waiting forever.
590 const NSTimeInterval kTimeoutSec = 3;
591 base::WaitUntilCondition(^bool() {
592 return callbackComplete;
593 }, nullptr, base::TimeDelta::FromSecondsD(kTimeoutSec));
594 EXPECT_TRUE(callbackComplete);
595 }
596
597 // Verifies that retina-scale images are deleted properly.
598 TEST_F(SnapshotCacheTest, TestDeleteRetinaImages) {
599 if ([SnapshotCache snapshotScaleForDevice] != 2.0) {
600 return;
601 }
602
603 // Create an image with retina scale.
604 UIGraphicsBeginImageContextWithOptions(
605 CGSizeMake(kSnapshotPixelSize, kSnapshotPixelSize), NO, 2.0);
606 CGContextRef context = UIGraphicsGetCurrentContext();
607 UIImage* image = GenerateRandomImage(context);
608 UIGraphicsEndImageContext();
609
610 // Add the image to the cache then call handle low memory to ensure the image
611 // is read from disk instead of the in-memory cache.
612 SnapshotCache* cache = [SnapshotCache sharedInstance];
613 NSString* const kSession = @"foo";
614 [cache setImage:image withSessionID:kSession];
615 [cache flushOperationQueue]; // ensure the file is written to disk.
616 [cache handleLowMemory];
617
618 // Verify the file was writted with @2x in the file name.
619 base::FilePath retinaFile = [cache imagePathForSessionID:kSession];
620 EXPECT_TRUE(base::PathExists(retinaFile));
621
622 // Delete the image.
623 [cache removeImageWithSessionID:kSession];
624 [cache flushOperationQueue]; // ensure the file is removed.
625
626 EXPECT_FALSE(base::PathExists(retinaFile));
627 }
628
629 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698