1 // Copyright (c) 2013 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 #include "base/memory/discardable_memory.h" 6 7 #include <algorithm> 8 9 #include "base/run_loop.h" 10 #include "testing/gtest/include/gtest/gtest.h" 11 12 #if defined(OS_ANDROID) 13 #include <limits> 14 #endif 15 16 namespace base { 17 namespace { 18 19 class DiscardableMemoryTest 20 : public testing::TestWithParam<DiscardableMemoryType> { 21 public: 22 DiscardableMemoryTest() : message_loop_(MessageLoop::TYPE_IO) { 23 // Register memory pressure listeners now that we have a message loop. 24 DiscardableMemory::RegisterMemoryPressureListeners(); 25 } 26 virtual ~DiscardableMemoryTest() { 27 DiscardableMemory::UnregisterMemoryPressureListeners(); 28 } 29 30 protected: 31 scoped_ptr<DiscardableMemory> CreateLockedMemory(size_t size) { 32 return DiscardableMemory::CreateLockedMemoryWithType( 33 GetParam(), size).Pass(); 34 } 35 36 private: 37 MessageLoop message_loop_; 38 }; 39 40 const size_t kSize = 1024; 41 42 TEST_P(DiscardableMemoryTest, IsNamed) { 43 std::string type_name(DiscardableMemory::GetTypeName(GetParam())); 44 EXPECT_NE("unknown", type_name); 45 EXPECT_EQ(GetParam(), DiscardableMemory::GetNamedType(type_name)); 46 } 47 48 bool IsNativeType(DiscardableMemoryType type) { 49 return 50 type == DISCARDABLE_MEMORY_TYPE_ASHMEM || 51 type == DISCARDABLE_MEMORY_TYPE_MAC; 52 } 53 54 TEST_P(DiscardableMemoryTest, SupportedNatively) { 55 std::vector<DiscardableMemoryType> supported_types; 56 DiscardableMemory::GetSupportedTypes(&supported_types); 57 #if defined(DISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY) 58 EXPECT_NE(0, std::count_if(supported_types.begin(), 59 supported_types.end(), 60 IsNativeType)); 61 #else 62 // If we ever have a platform that decides at runtime if it can support 63 // discardable memory natively, then we'll have to add a 'never supported 64 // natively' define for this case. At present, if it's not always supported 65 // natively, it's never supported. 66 EXPECT_EQ(0, std::count_if(supported_types.begin(), 67 supported_types.end(), 68 IsNativeType)); 69 #endif 70 } 71 72 // Test Lock() and Unlock() functionalities. 73 TEST_P(DiscardableMemoryTest, LockAndUnLock) { 74 const scoped_ptr<DiscardableMemory> memory(CreateLockedMemory(kSize)); 75 ASSERT_TRUE(memory); 76 void* addr = memory->Memory(); 77 ASSERT_NE(static_cast<void*>(NULL), addr); 78 79 memory->Unlock(); 80 81 EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_FAILED, memory->Lock()); 82 addr = memory->Memory(); 83 ASSERT_NE(static_cast<void*>(NULL), addr); 84 85 memory->Unlock(); 86 } 87 88 // Test delete a discardable memory while it is locked. 89 TEST_P(DiscardableMemoryTest, DeleteWhileLocked) { 90 const scoped_ptr<DiscardableMemory> memory(CreateLockedMemory(kSize)); 91 ASSERT_TRUE(memory); 92 } 93 94 // Test forced purging. 95 TEST_P(DiscardableMemoryTest, Purge) { 96 const scoped_ptr<DiscardableMemory> memory(CreateLockedMemory(kSize)); 97 ASSERT_TRUE(memory); 98 memory->Unlock(); 99 100 DiscardableMemory::PurgeForTesting(); 101 EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, memory->Lock()); 102 } 103 104 #if !defined(NDEBUG) && !defined(OS_ANDROID) 105 // Death tests are not supported with Android APKs. 106 TEST_P(DiscardableMemoryTest, UnlockedMemoryAccessCrashesInDebugMode) { 107 const scoped_ptr<DiscardableMemory> memory(CreateLockedMemory(kSize)); 108 ASSERT_TRUE(memory); 109 memory->Unlock(); 110 ASSERT_DEATH_IF_SUPPORTED( 111 { *static_cast<int*>(memory->Memory()) = 0xdeadbeef; }, ".*"); 112 } 113 #endif 114 115 std::vector<DiscardableMemoryType> GetSupportedDiscardableMemoryTypes() { 116 std::vector<DiscardableMemoryType> supported_types; 117 DiscardableMemory::GetSupportedTypes(&supported_types); 118 return supported_types; 119 } 120 121 INSTANTIATE_TEST_CASE_P( 122 DiscardableMemoryTests, 123 DiscardableMemoryTest, 124 ::testing::ValuesIn(GetSupportedDiscardableMemoryTypes())); 125 126 } // namespace 127 } // namespace base 128