OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/chrome/browser/snapshots/snapshot_cache.h" | 5 #import "ios/chrome/browser/snapshots/snapshot_cache.h" |
6 | 6 |
7 #import <Foundation/Foundation.h> | 7 #import <Foundation/Foundation.h> |
8 | 8 |
9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
11 #include "base/format_macros.h" | 11 #include "base/format_macros.h" |
| 12 #include "base/ios/ios_util.h" |
12 #include "base/location.h" | 13 #include "base/location.h" |
13 #include "base/mac/bind_objc_block.h" | 14 #include "base/mac/bind_objc_block.h" |
14 #include "base/mac/scoped_nsautorelease_pool.h" | 15 #include "base/mac/scoped_nsautorelease_pool.h" |
15 #include "base/run_loop.h" | 16 #include "base/run_loop.h" |
16 #include "base/strings/sys_string_conversions.h" | 17 #include "base/strings/sys_string_conversions.h" |
17 #include "base/time/time.h" | 18 #include "base/time/time.h" |
18 #import "ios/chrome/browser/snapshots/snapshot_cache_internal.h" | 19 #include "ios/chrome/browser/experimental_flags.h" |
| 20 #include "ios/chrome/browser/ui/ui_util.h" |
19 #include "ios/web/public/test/test_web_thread_bundle.h" | 21 #include "ios/web/public/test/test_web_thread_bundle.h" |
20 #include "ios/web/public/web_thread.h" | 22 #include "ios/web/public/web_thread.h" |
21 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
22 #include "testing/gtest_mac.h" | 24 #include "testing/gtest_mac.h" |
23 #include "testing/platform_test.h" | 25 #include "testing/platform_test.h" |
24 | 26 |
25 static const NSUInteger kSessionCount = 10; | 27 static const NSUInteger kSessionCount = 10; |
26 static const NSUInteger kSnapshotPixelSize = 8; | 28 static const NSUInteger kSnapshotPixelSize = 8; |
27 | 29 |
| 30 // Promote some implementation methods to public. |
| 31 @interface SnapshotCache (Testing) |
| 32 + (base::FilePath)imagePathForSessionID:(NSString*)sessionID; |
| 33 + (base::FilePath)greyImagePathForSessionID:(NSString*)sessionID; |
| 34 - (void)handleLowMemory; |
| 35 @end |
28 | 36 |
29 namespace { | 37 namespace { |
30 | 38 |
31 class SnapshotCacheTest : public PlatformTest { | 39 class SnapshotCacheTest : public PlatformTest { |
32 protected: | 40 protected: |
33 // Build an array of session names and an array of UIImages filled with | 41 // Build an array of session names and an array of UIImages filled with |
34 // random colors. | 42 // random colors. |
35 void SetUp() override { | 43 void SetUp() override { |
36 PlatformTest::SetUp(); | 44 PlatformTest::SetUp(); |
37 snapshotCache_.reset([[SnapshotCache alloc] init]); | 45 snapshotCache_.reset([[SnapshotCache alloc] init]); |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 *green = lastChannel - *green; | 197 *green = lastChannel - *green; |
190 *blue = lastChannel - *blue; | 198 *blue = lastChannel - *blue; |
191 } | 199 } |
192 } | 200 } |
193 | 201 |
194 const char* GetPixelData(CGImageRef cgImage) { | 202 const char* GetPixelData(CGImageRef cgImage) { |
195 CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(cgImage)); | 203 CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(cgImage)); |
196 return reinterpret_cast<const char*>(CFDataGetBytePtr(data)); | 204 return reinterpret_cast<const char*>(CFDataGetBytePtr(data)); |
197 } | 205 } |
198 | 206 |
199 void TriggerMemoryWarning() { | |
200 // _performMemoryWarning is a private API and musn't be compiled into | |
201 // official builds. | |
202 [[UIApplication sharedApplication] | |
203 performSelector:@selector(_performMemoryWarning)]; | |
204 } | |
205 | |
206 web::TestWebThreadBundle thread_bundle_; | 207 web::TestWebThreadBundle thread_bundle_; |
207 base::scoped_nsobject<SnapshotCache> snapshotCache_; | 208 base::scoped_nsobject<SnapshotCache> snapshotCache_; |
208 base::scoped_nsobject<NSMutableArray> testSessions_; | 209 base::scoped_nsobject<NSMutableArray> testSessions_; |
209 base::scoped_nsobject<NSMutableArray> testImages_; | 210 base::scoped_nsobject<NSMutableArray> testImages_; |
210 }; | 211 }; |
211 | 212 |
212 // This test simply put all the snapshots in the cache and then gets them back | 213 // This test simply put all the snapshots in the cache and then gets them back |
213 // As the snapshots are kept in memory, the same pointer can be retrieved. | 214 // As the snapshots are kept in memory, the same pointer can be retrieved. |
214 // This test also checks that images are correctly removed from the disk. | 215 // This test also checks that images are correctly removed from the disk. |
215 TEST_F(SnapshotCacheTest, Cache) { | 216 TEST_F(SnapshotCacheTest, Cache) { |
| 217 // Don't run on tablets because color snapshots are not cached so this test |
| 218 // can't compare the UIImage pointers directly. |
| 219 if (IsIPadIdiom() && !experimental_flags::IsTabSwitcherEnabled()) { |
| 220 return; |
| 221 } |
| 222 |
216 SnapshotCache* cache = GetSnapshotCache(); | 223 SnapshotCache* cache = GetSnapshotCache(); |
217 | 224 |
218 if (![cache inMemoryCacheIsEnabled]) | |
219 return; | |
220 | |
221 NSUInteger expectedCacheSize = kSessionCount; | 225 NSUInteger expectedCacheSize = kSessionCount; |
222 if ([cache usesLRUCache]) | 226 if (experimental_flags::IsLRUSnapshotCacheEnabled()) |
223 expectedCacheSize = MIN(kSessionCount, [cache lruCacheMaxSize]); | 227 expectedCacheSize = MIN(kSessionCount, [cache lruCacheMaxSize]); |
224 | 228 |
225 // Put all images in the cache. | 229 // Put all images in the cache. |
226 for (NSUInteger i = 0; i < expectedCacheSize; ++i) { | 230 for (NSUInteger i = 0; i < expectedCacheSize; ++i) { |
227 UIImage* image = [testImages_ objectAtIndex:i]; | 231 UIImage* image = [testImages_ objectAtIndex:i]; |
228 NSString* sessionID = [testSessions_ objectAtIndex:i]; | 232 NSString* sessionID = [testSessions_ objectAtIndex:i]; |
229 [cache setImage:image withSessionID:sessionID]; | 233 [cache setImage:image withSessionID:sessionID]; |
230 } | 234 } |
231 | 235 |
232 // Get images back. | 236 // Get images back. |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 | 340 |
337 base::FilePath path([SnapshotCache imagePathForSessionID:sessionID]); | 341 base::FilePath path([SnapshotCache imagePathForSessionID:sessionID]); |
338 if (i == 0) | 342 if (i == 0) |
339 EXPECT_TRUE(base::PathExists(path)); | 343 EXPECT_TRUE(base::PathExists(path)); |
340 else | 344 else |
341 EXPECT_FALSE(base::PathExists(path)); | 345 EXPECT_FALSE(base::PathExists(path)); |
342 } | 346 } |
343 } | 347 } |
344 | 348 |
345 // Loads the color images into the cache, and pins two of them. Ensures that | 349 // Loads the color images into the cache, and pins two of them. Ensures that |
346 // only the two pinned IDs remain in memory after a memory warning. | 350 // only the two pinned IDs remain in memory after a call to -handleLowMemory. |
347 TEST_F(SnapshotCacheTest, HandleMemoryWarning) { | 351 TEST_F(SnapshotCacheTest, HandleLowMemory) { |
| 352 // TODO(droger): This test fails on iPad iOS8 device: http://crbug.com/455209 |
| 353 #if !TARGET_IPHONE_SIMULATOR |
| 354 if (IsIPadIdiom() && base::ios::IsRunningOnIOS8OrLater()) { |
| 355 LOG(WARNING) << "Test disabled on iPad iOS8 device."; |
| 356 return; |
| 357 } |
| 358 #endif |
| 359 |
348 LoadAllColorImagesIntoCache(true); | 360 LoadAllColorImagesIntoCache(true); |
349 | 361 |
350 SnapshotCache* cache = GetSnapshotCache(); | 362 SnapshotCache* cache = GetSnapshotCache(); |
351 | 363 |
352 NSString* firstPinnedID = [testSessions_ objectAtIndex:4]; | 364 NSString* firstPinnedID = [testSessions_ objectAtIndex:4]; |
353 NSString* secondPinnedID = [testSessions_ objectAtIndex:6]; | 365 NSString* secondPinnedID = [testSessions_ objectAtIndex:6]; |
354 NSMutableSet* set = [NSMutableSet set]; | 366 NSMutableSet* set = [NSMutableSet set]; |
355 [set addObject:firstPinnedID]; | 367 [set addObject:firstPinnedID]; |
356 [set addObject:secondPinnedID]; | 368 [set addObject:secondPinnedID]; |
357 cache.pinnedIDs = set; | 369 cache.pinnedIDs = set; |
358 | 370 |
359 TriggerMemoryWarning(); | 371 if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) |
| 372 [cache handleLowMemory]; |
360 | 373 |
361 EXPECT_EQ(YES, [cache hasImageInMemory:firstPinnedID]); | 374 BOOL expectedValue = YES; |
362 EXPECT_EQ(YES, [cache hasImageInMemory:secondPinnedID]); | 375 if (IsIPadIdiom() && !experimental_flags::IsTabSwitcherEnabled()) |
| 376 expectedValue = NO; |
| 377 |
| 378 EXPECT_EQ(expectedValue, [cache hasImageInMemory:firstPinnedID]); |
| 379 EXPECT_EQ(expectedValue, [cache hasImageInMemory:secondPinnedID]); |
363 | 380 |
364 NSString* notPinnedID = [testSessions_ objectAtIndex:2]; | 381 NSString* notPinnedID = [testSessions_ objectAtIndex:2]; |
365 EXPECT_FALSE([cache hasImageInMemory:notPinnedID]); | 382 EXPECT_FALSE([cache hasImageInMemory:notPinnedID]); |
366 | 383 |
367 // Wait for the final image to be pulled off disk. | 384 // Wait for the final image to be pulled off disk. |
368 FlushRunLoops(); | 385 FlushRunLoops(); |
369 } | 386 } |
370 | 387 |
371 // Tests that createGreyCache creates the grey snapshots in the background, | 388 // Tests that createGreyCache creates the grey snapshots in the background, |
372 // from color images in the in-memory cache. When the grey images are all | 389 // from color images in the in-memory cache. When the grey images are all |
(...skipping 26 matching lines...) Expand all Loading... |
399 | 416 |
400 // Same as previous test, except that all the color images are on disk, | 417 // Same as previous test, except that all the color images are on disk, |
401 // rather than in memory. | 418 // rather than in memory. |
402 // Disabled due to the greyImage crash. b/8048597 | 419 // Disabled due to the greyImage crash. b/8048597 |
403 TEST_F(SnapshotCacheTest, CreateGreyCacheFromDisk) { | 420 TEST_F(SnapshotCacheTest, CreateGreyCacheFromDisk) { |
404 LoadAllColorImagesIntoCache(true); | 421 LoadAllColorImagesIntoCache(true); |
405 | 422 |
406 // Remove color images from in-memory cache. | 423 // Remove color images from in-memory cache. |
407 SnapshotCache* cache = GetSnapshotCache(); | 424 SnapshotCache* cache = GetSnapshotCache(); |
408 | 425 |
409 TriggerMemoryWarning(); | 426 if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) |
| 427 [cache handleLowMemory]; |
410 | 428 |
411 // Request the creation of a grey image cache for all images. | 429 // Request the creation of a grey image cache for all images. |
412 [cache createGreyCache:testSessions_]; | 430 [cache createGreyCache:testSessions_]; |
413 | 431 |
414 // Wait for them to be put into the grey image cache. | 432 // Wait for them to be put into the grey image cache. |
415 WaitForGreyImagesInCache(kSessionCount); | 433 WaitForGreyImagesInCache(kSessionCount); |
416 | 434 |
417 __block NSUInteger numberOfCallbacks = 0; | 435 __block NSUInteger numberOfCallbacks = 0; |
418 for (NSUInteger i = 0; i < kSessionCount; ++i) { | 436 for (NSUInteger i = 0; i < kSessionCount; ++i) { |
419 NSString* sessionID = [testSessions_ objectAtIndex:i]; | 437 NSString* sessionID = [testSessions_ objectAtIndex:i]; |
(...skipping 20 matching lines...) Expand all Loading... |
440 [sessionIDs addObject:[testSessions_ objectAtIndex:0]]; | 458 [sessionIDs addObject:[testSessions_ objectAtIndex:0]]; |
441 [sessionIDs addObject:[testSessions_ objectAtIndex:1]]; | 459 [sessionIDs addObject:[testSessions_ objectAtIndex:1]]; |
442 [sessionIDs addObject:[testSessions_ objectAtIndex:2]]; | 460 [sessionIDs addObject:[testSessions_ objectAtIndex:2]]; |
443 | 461 |
444 SnapshotCache* cache = GetSnapshotCache(); | 462 SnapshotCache* cache = GetSnapshotCache(); |
445 | 463 |
446 // Put 3 images in the cache. | 464 // Put 3 images in the cache. |
447 LoadColorImagesIntoCache(kNumImages, true); | 465 LoadColorImagesIntoCache(kNumImages, true); |
448 // Make sure the color images are only on disk, to ensure the background | 466 // Make sure the color images are only on disk, to ensure the background |
449 // thread is slow enough to queue up the requests. | 467 // thread is slow enough to queue up the requests. |
450 TriggerMemoryWarning(); | 468 if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) |
| 469 [cache handleLowMemory]; |
451 | 470 |
452 // Enable the grey image cache. | 471 // Enable the grey image cache. |
453 [cache createGreyCache:sessionIDs]; | 472 [cache createGreyCache:sessionIDs]; |
454 | 473 |
455 // Request the grey versions | 474 // Request the grey versions |
456 __block BOOL firstCallbackCalled = NO; | 475 __block BOOL firstCallbackCalled = NO; |
457 __block BOOL secondCallbackCalled = NO; | 476 __block BOOL secondCallbackCalled = NO; |
458 __block BOOL thirdCallbackCalled = NO; | 477 __block BOOL thirdCallbackCalled = NO; |
459 [cache greyImageForSessionID:[testSessions_ objectAtIndex:0] | 478 [cache greyImageForSessionID:[testSessions_ objectAtIndex:0] |
460 callback:^(UIImage*) { | 479 callback:^(UIImage*) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 CGContextRef context = UIGraphicsGetCurrentContext(); | 530 CGContextRef context = UIGraphicsGetCurrentContext(); |
512 UIImage* image = GenerateRandomImage(context); | 531 UIImage* image = GenerateRandomImage(context); |
513 UIGraphicsEndImageContext(); | 532 UIGraphicsEndImageContext(); |
514 | 533 |
515 // Add the image to the cache then call handle low memory to ensure the image | 534 // Add the image to the cache then call handle low memory to ensure the image |
516 // is read from disk instead of the in-memory cache. | 535 // is read from disk instead of the in-memory cache. |
517 SnapshotCache* cache = GetSnapshotCache(); | 536 SnapshotCache* cache = GetSnapshotCache(); |
518 NSString* const kSession = @"foo"; | 537 NSString* const kSession = @"foo"; |
519 [cache setImage:image withSessionID:kSession]; | 538 [cache setImage:image withSessionID:kSession]; |
520 FlushRunLoops(); // ensure the file is written to disk. | 539 FlushRunLoops(); // ensure the file is written to disk. |
521 TriggerMemoryWarning(); | 540 if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) |
| 541 [cache handleLowMemory]; |
522 | 542 |
523 // Retrive the image and have the callback verify the size and scale. | 543 // Retrive the image and have the callback verify the size and scale. |
524 __block BOOL callbackComplete = NO; | 544 __block BOOL callbackComplete = NO; |
525 [cache retrieveImageForSessionID:kSession | 545 [cache retrieveImageForSessionID:kSession |
526 callback:^(UIImage* imageFromDisk) { | 546 callback:^(UIImage* imageFromDisk) { |
527 EXPECT_EQ(image.size.width, | 547 EXPECT_EQ(image.size.width, |
528 imageFromDisk.size.width); | 548 imageFromDisk.size.width); |
529 EXPECT_EQ(image.size.height, | 549 EXPECT_EQ(image.size.height, |
530 imageFromDisk.size.height); | 550 imageFromDisk.size.height); |
531 EXPECT_EQ(image.scale, imageFromDisk.scale); | 551 EXPECT_EQ(image.scale, imageFromDisk.scale); |
(...skipping 15 matching lines...) Expand all Loading... |
547 CGContextRef context = UIGraphicsGetCurrentContext(); | 567 CGContextRef context = UIGraphicsGetCurrentContext(); |
548 UIImage* image = GenerateRandomImage(context); | 568 UIImage* image = GenerateRandomImage(context); |
549 UIGraphicsEndImageContext(); | 569 UIGraphicsEndImageContext(); |
550 | 570 |
551 // Add the image to the cache then call handle low memory to ensure the image | 571 // Add the image to the cache then call handle low memory to ensure the image |
552 // is read from disk instead of the in-memory cache. | 572 // is read from disk instead of the in-memory cache. |
553 SnapshotCache* cache = GetSnapshotCache(); | 573 SnapshotCache* cache = GetSnapshotCache(); |
554 NSString* const kSession = @"foo"; | 574 NSString* const kSession = @"foo"; |
555 [cache setImage:image withSessionID:kSession]; | 575 [cache setImage:image withSessionID:kSession]; |
556 FlushRunLoops(); // ensure the file is written to disk. | 576 FlushRunLoops(); // ensure the file is written to disk. |
557 TriggerMemoryWarning(); | 577 if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) |
| 578 [cache handleLowMemory]; |
558 | 579 |
559 // Verify the file was writted with @2x in the file name. | 580 // Verify the file was writted with @2x in the file name. |
560 base::FilePath retinaFile = [SnapshotCache imagePathForSessionID:kSession]; | 581 base::FilePath retinaFile = [SnapshotCache imagePathForSessionID:kSession]; |
561 EXPECT_TRUE(base::PathExists(retinaFile)); | 582 EXPECT_TRUE(base::PathExists(retinaFile)); |
562 | 583 |
563 // Delete the image. | 584 // Delete the image. |
564 [cache removeImageWithSessionID:kSession]; | 585 [cache removeImageWithSessionID:kSession]; |
565 FlushRunLoops(); // ensure the file is removed. | 586 FlushRunLoops(); // ensure the file is removed. |
566 | 587 |
567 EXPECT_FALSE(base::PathExists(retinaFile)); | 588 EXPECT_FALSE(base::PathExists(retinaFile)); |
568 } | 589 } |
569 | 590 |
570 } // namespace | 591 } // namespace |
OLD | NEW |