151c0b2f7Stbbdev /* 2*cb88c51cSIlya Isaev Copyright (c) 2005-2022 Intel Corporation 351c0b2f7Stbbdev 451c0b2f7Stbbdev Licensed under the Apache License, Version 2.0 (the "License"); 551c0b2f7Stbbdev you may not use this file except in compliance with the License. 651c0b2f7Stbbdev You may obtain a copy of the License at 751c0b2f7Stbbdev 851c0b2f7Stbbdev http://www.apache.org/licenses/LICENSE-2.0 951c0b2f7Stbbdev 1051c0b2f7Stbbdev Unless required by applicable law or agreed to in writing, software 1151c0b2f7Stbbdev distributed under the License is distributed on an "AS IS" BASIS, 1251c0b2f7Stbbdev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1351c0b2f7Stbbdev See the License for the specific language governing permissions and 1451c0b2f7Stbbdev limitations under the License. 1551c0b2f7Stbbdev */ 1651c0b2f7Stbbdev 1751c0b2f7Stbbdev #define TBB_PREVIEW_CONCURRENT_LRU_CACHE 1 1851c0b2f7Stbbdev 19b15aabb3Stbbdev #if __INTEL_COMPILER && _MSC_VER 20b15aabb3Stbbdev #pragma warning(disable : 2586) // decorated name length exceeded, name was truncated 21b15aabb3Stbbdev #endif 22b15aabb3Stbbdev 2351c0b2f7Stbbdev #include "common/test.h" 24*cb88c51cSIlya Isaev #include "common/utils.h" 2551c0b2f7Stbbdev #include <tbb/concurrent_lru_cache.h> 2651c0b2f7Stbbdev #include <common/concurrent_lru_cache_common.h> 2751c0b2f7Stbbdev 2851c0b2f7Stbbdev //! \file test_concurrent_lru_cache.cpp 2951c0b2f7Stbbdev //! \brief Test for [preview] functionality 3051c0b2f7Stbbdev 3151c0b2f7Stbbdev //----------------------------------------------------------------------------- 3251c0b2f7Stbbdev // Concurrent LRU Cache Tests: Cache Test Cases 3351c0b2f7Stbbdev //----------------------------------------------------------------------------- 3451c0b2f7Stbbdev 3551c0b2f7Stbbdev //! \brief \ref error_guessing 3651c0b2f7Stbbdev TEST_CASE("basic test for return value") { 3751c0b2f7Stbbdev using preset = concurrent_lru_cache_presets::preset_default<int, int>; 3851c0b2f7Stbbdev __anoncd5487920102(int ) 3951c0b2f7Stbbdev auto dummy_f = [](int /*key*/) -> int { return 0xDEADBEEF; }; 4051c0b2f7Stbbdev std::size_t number_of_lru_history_items = 8; 4151c0b2f7Stbbdev 4251c0b2f7Stbbdev preset preset_object{dummy_f, number_of_lru_history_items}; 4351c0b2f7Stbbdev preset::cache_type& cache = preset_object.cache; 4451c0b2f7Stbbdev 4551c0b2f7Stbbdev int dummy_key = 1; 4651c0b2f7Stbbdev REQUIRE_MESSAGE( 4751c0b2f7Stbbdev dummy_f(dummy_key) == cache[dummy_key].value(), 4851c0b2f7Stbbdev "cache operator() must return only values obtained from value function"); 4951c0b2f7Stbbdev } 5051c0b2f7Stbbdev 5151c0b2f7Stbbdev //! \brief \ref error_guessing 5251c0b2f7Stbbdev TEST_CASE("basic test for unused objects") { 5351c0b2f7Stbbdev using preset = concurrent_lru_cache_presets::preset_instance_count; 5451c0b2f7Stbbdev preset preset_object{}; 5551c0b2f7Stbbdev 5651c0b2f7Stbbdev for (std::size_t i = 0; i < preset_object.number_of_lru_history_items; ++i) 5751c0b2f7Stbbdev preset_object.cache[i]; 5851c0b2f7Stbbdev 5951c0b2f7Stbbdev REQUIRE_MESSAGE( 6051c0b2f7Stbbdev preset_object.source.instances_count() > 1, 6151c0b2f7Stbbdev "cache should store some unused objects"); 6251c0b2f7Stbbdev } 6351c0b2f7Stbbdev 6451c0b2f7Stbbdev //! \brief \ref error_guessing 6551c0b2f7Stbbdev TEST_CASE("basic test for unused object limit") { 6651c0b2f7Stbbdev using preset = concurrent_lru_cache_presets::preset_instance_count; 6751c0b2f7Stbbdev preset preset_object{}; 6851c0b2f7Stbbdev 6951c0b2f7Stbbdev for (std::size_t i = 0; i < preset_object.number_of_lru_history_items + 1; ++i) 7051c0b2f7Stbbdev preset_object.cache[i]; 7151c0b2f7Stbbdev 7251c0b2f7Stbbdev REQUIRE_MESSAGE( 7351c0b2f7Stbbdev preset_object.source.instances_count() == preset_object.number_of_lru_history_items + 1, 7451c0b2f7Stbbdev "cache should respect number of stored unused objects to number passed in constructor"); 7551c0b2f7Stbbdev } 7651c0b2f7Stbbdev 7751c0b2f7Stbbdev //! \brief \ref error_guessing 7851c0b2f7Stbbdev TEST_CASE("basic test for eviction order") { 7951c0b2f7Stbbdev using preset = concurrent_lru_cache_presets::preset_map_instance_count; 8051c0b2f7Stbbdev preset preset_object{}; 8151c0b2f7Stbbdev 8251c0b2f7Stbbdev REQUIRE_MESSAGE( 8351c0b2f7Stbbdev preset_object.number_of_lru_history_items > 2, 8451c0b2f7Stbbdev "incorrect test setup"); 8551c0b2f7Stbbdev 8651c0b2f7Stbbdev preset_object.fill_up_cache(0, preset_object.number_of_lru_history_items); 8751c0b2f7Stbbdev 8851c0b2f7Stbbdev // heat up first element 8951c0b2f7Stbbdev preset_object.cache[0]; 9051c0b2f7Stbbdev 9151c0b2f7Stbbdev // cause eviction; 9251c0b2f7Stbbdev preset_object.cache[preset_object.number_of_lru_history_items]; 9351c0b2f7Stbbdev 9451c0b2f7Stbbdev bool is_correct = preset_object.is_evicted(1) && !preset_object.is_evicted(0); 9551c0b2f7Stbbdev REQUIRE_MESSAGE(is_correct, "cache should evict items in lru order"); 9651c0b2f7Stbbdev } 9751c0b2f7Stbbdev 9851c0b2f7Stbbdev //! \brief \ref error_guessing 9951c0b2f7Stbbdev TEST_CASE("basic test for eviction of only unused items") { 10051c0b2f7Stbbdev using preset = concurrent_lru_cache_presets::preset_map_instance_count; 10151c0b2f7Stbbdev preset preset_object{}; 10251c0b2f7Stbbdev 10351c0b2f7Stbbdev preset::handle_type h = preset_object.cache[0]; 10451c0b2f7Stbbdev 10551c0b2f7Stbbdev //cause eviction 10651c0b2f7Stbbdev preset_object.fill_up_cache(1, preset_object.number_of_lru_history_items+2); 10751c0b2f7Stbbdev 10851c0b2f7Stbbdev bool is_correct = preset_object.is_evicted(1) && !preset_object.is_evicted(0); 10951c0b2f7Stbbdev REQUIRE_MESSAGE(is_correct, "cache should not evict items in use"); 11051c0b2f7Stbbdev } 11151c0b2f7Stbbdev 11251c0b2f7Stbbdev //! \brief \ref error_guessing 11351c0b2f7Stbbdev TEST_CASE("basic test for eviction of only unused items 2") { 11451c0b2f7Stbbdev using preset = concurrent_lru_cache_presets::preset_map_instance_count; 11551c0b2f7Stbbdev preset preset_object{}; 11651c0b2f7Stbbdev 11751c0b2f7Stbbdev preset::handle_type h = preset_object.cache[0]; 11851c0b2f7Stbbdev { 11951c0b2f7Stbbdev preset::handle_type h1 = preset_object.cache[0]; 12051c0b2f7Stbbdev } 12151c0b2f7Stbbdev 12251c0b2f7Stbbdev //cause eviction 12351c0b2f7Stbbdev preset_object.fill_up_cache(1,preset_object.number_of_lru_history_items+2); 12451c0b2f7Stbbdev 12551c0b2f7Stbbdev bool is_correct = preset_object.is_evicted(1) && !preset_object.is_evicted(0); 12651c0b2f7Stbbdev REQUIRE_MESSAGE(is_correct, "cache should not evict items in use"); 12751c0b2f7Stbbdev } 12851c0b2f7Stbbdev 129*cb88c51cSIlya Isaev //! \brief \ref error_guessing 130*cb88c51cSIlya Isaev TEST_CASE("basic test for handling case when number_of_lru_history_items is zero") { __anoncd5487920202(int) 131*cb88c51cSIlya Isaev auto foo = [] (int) { 132*cb88c51cSIlya Isaev return utils::LifeTrackableObject{}; 133*cb88c51cSIlya Isaev }; 134*cb88c51cSIlya Isaev using cache_type = tbb::concurrent_lru_cache<int, utils::LifeTrackableObject, decltype(foo)>; 135*cb88c51cSIlya Isaev cache_type cache{foo, 0}; 136*cb88c51cSIlya Isaev 137*cb88c51cSIlya Isaev for(int i = 0; i < 10; ++i) { 138*cb88c51cSIlya Isaev // Check that no history is stored when my_history_list_capacity is 0. 139*cb88c51cSIlya Isaev // In this case, when trying to fill the cache, the items will be deleted if reference was not taken. 140*cb88c51cSIlya Isaev const utils::LifeTrackableObject* obj_addr = &cache[1].value(); 141*cb88c51cSIlya Isaev REQUIRE_MESSAGE(utils::LifeTrackableObject::is_alive(obj_addr) == false, "when number_of_lru_history_items is zero, element must be erased after use"); 142*cb88c51cSIlya Isaev } 143*cb88c51cSIlya Isaev 144*cb88c51cSIlya Isaev cache_type::handle h = cache[1]; 145*cb88c51cSIlya Isaev const utils::LifeTrackableObject* obj_addr = &h.value(); 146*cb88c51cSIlya Isaev auto& object_set = utils::LifeTrackableObject::set(); 147*cb88c51cSIlya Isaev for(int i = 0; i < 10; ++i) { 148*cb88c51cSIlya Isaev // Verify that item will still be alive if there is a handle holding that item. 149*cb88c51cSIlya Isaev cache[1]; 150*cb88c51cSIlya Isaev REQUIRE_MESSAGE(utils::LifeTrackableObject::is_alive(obj_addr), "the object with the key=1 was destroyed but should not"); 151*cb88c51cSIlya Isaev REQUIRE_MESSAGE(object_set.size() == 1, "no other values should be added"); 152*cb88c51cSIlya Isaev } 153*cb88c51cSIlya Isaev } 154