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