forked from caoXF/curve
360 lines
11 KiB
C++
360 lines
11 KiB
C++
/*
|
|
* Copyright (c) 2020 NetEase Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/*
|
|
* Project: curve
|
|
* Created Date: 20211010
|
|
* Author: xuchaojie,lixiaocui
|
|
*/
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <glog/logging.h>
|
|
#include <cstdint>
|
|
|
|
#include "src/common/lru_cache.h"
|
|
#include "src/common/timeutility.h"
|
|
|
|
namespace curve {
|
|
namespace common {
|
|
|
|
TEST(TestCacheMetrics, testall) {
|
|
CacheMetrics cacheMetrics("LRUCache");
|
|
|
|
// 1. 新增数据项
|
|
cacheMetrics.UpdateAddToCacheCount();
|
|
ASSERT_EQ(1, cacheMetrics.cacheCount.get_value());
|
|
|
|
cacheMetrics.UpdateAddToCacheBytes(1000);
|
|
ASSERT_EQ(1000, cacheMetrics.cacheBytes.get_value());
|
|
|
|
// 2. 移除数据项
|
|
cacheMetrics.UpdateRemoveFromCacheCount();
|
|
ASSERT_EQ(0, cacheMetrics.cacheCount.get_value());
|
|
|
|
cacheMetrics.UpdateRemoveFromCacheBytes(200);
|
|
ASSERT_EQ(800, cacheMetrics.cacheBytes.get_value());
|
|
|
|
// 3. cache命中
|
|
ASSERT_EQ(0, cacheMetrics.cacheHit.get_value());
|
|
cacheMetrics.OnCacheHit();
|
|
ASSERT_EQ(1, cacheMetrics.cacheHit.get_value());
|
|
|
|
// 4. cache未命中
|
|
ASSERT_EQ(0, cacheMetrics.cacheMiss.get_value());
|
|
cacheMetrics.OnCacheMiss();
|
|
ASSERT_EQ(1, cacheMetrics.cacheMiss.get_value());
|
|
}
|
|
|
|
TEST(CaCheTest, test_cache_with_capacity_limit) {
|
|
int maxCount = 5;
|
|
auto cache = std::make_shared<LRUCache<std::string, std::string>>(maxCount,
|
|
std::make_shared<CacheMetrics>("LruCache"));
|
|
|
|
// 1. 测试 put/get
|
|
uint64_t cacheSize = 0;
|
|
for (int i = 1; i <= maxCount + 1; i++) {
|
|
std::string eliminated;
|
|
cache->Put(std::to_string(i), std::to_string(i), &eliminated);
|
|
if (i <= maxCount) {
|
|
cacheSize += std::to_string(i).size() * 2;
|
|
ASSERT_EQ(i, cache->GetCacheMetrics()->cacheCount.get_value());
|
|
} else {
|
|
cacheSize +=
|
|
std::to_string(i).size() * 2 - std::to_string(1).size() * 2;
|
|
ASSERT_EQ(
|
|
cacheSize, cache->GetCacheMetrics()->cacheBytes.get_value());
|
|
}
|
|
|
|
std::string res;
|
|
ASSERT_TRUE(cache->Get(std::to_string(i), &res));
|
|
ASSERT_EQ(std::to_string(i), res);
|
|
}
|
|
|
|
// 2. 第一个元素被剔出
|
|
std::string res;
|
|
ASSERT_FALSE(cache->Get(std::to_string(1), &res));
|
|
for (int i = 2; i <= maxCount + 1; i++) {
|
|
ASSERT_TRUE(cache->Get(std::to_string(i), &res));
|
|
ASSERT_EQ(std::to_string(i), res);
|
|
}
|
|
|
|
// 3. 测试删除元素
|
|
// 删除不存在的元素
|
|
cache->Remove("1");
|
|
// 删除list中存在的元素
|
|
cache->Remove("2");
|
|
ASSERT_FALSE(cache->Get("2", &res));
|
|
cacheSize -= std::to_string(2).size() * 2;
|
|
ASSERT_EQ(maxCount - 1, cache->GetCacheMetrics()->cacheCount.get_value());
|
|
ASSERT_EQ(cacheSize, cache->GetCacheMetrics()->cacheBytes.get_value());
|
|
|
|
// 4. 重复put
|
|
std::string eliminated;
|
|
cache->Put("4", "hello", &eliminated);
|
|
ASSERT_TRUE(cache->Get("4", &res));
|
|
ASSERT_EQ("hello", res);
|
|
ASSERT_EQ(maxCount - 1, cache->GetCacheMetrics()->cacheCount.get_value());
|
|
cacheSize -= std::to_string(4).size() * 2;
|
|
cacheSize += std::to_string(4).size() + std::string("hello").size();
|
|
ASSERT_EQ(cacheSize, cache->GetCacheMetrics()->cacheBytes.get_value());
|
|
}
|
|
|
|
TEST(CaCheTest, test_cache_with_capacity_no_limit) {
|
|
auto cache = std::make_shared<LRUCache<std::string, std::string>>(
|
|
std::make_shared<CacheMetrics>("LruCache"));
|
|
|
|
// 1. 测试 put/get
|
|
std::string res;
|
|
for (int i = 1; i <= 10; i++) {
|
|
std::string eliminated;
|
|
cache->Put(std::to_string(i), std::to_string(i), &eliminated);
|
|
ASSERT_TRUE(cache->Get(std::to_string(i), &res));
|
|
ASSERT_EQ(std::to_string(i), res);
|
|
}
|
|
|
|
// 2. 测试元素删除
|
|
cache->Remove("1");
|
|
ASSERT_FALSE(cache->Get("1", &res));
|
|
}
|
|
|
|
TEST(CaCheTest, TestCacheHitAndMissMetric) {
|
|
auto cache = std::make_shared<LRUCache<std::string, std::string>>(
|
|
std::make_shared<CacheMetrics>("LruCache"));
|
|
ASSERT_EQ(0, cache->GetCacheMetrics()->cacheHit.get_value());
|
|
ASSERT_EQ(0, cache->GetCacheMetrics()->cacheMiss.get_value());
|
|
|
|
std::string existKey = "hello";
|
|
std::string notExistKey = "world";
|
|
std::string eliminated;
|
|
cache->Put(existKey, existKey, &eliminated);
|
|
|
|
std::string out;
|
|
for (int i = 0; i < 10; ++i) {
|
|
ASSERT_TRUE(cache->Get(existKey, &out));
|
|
ASSERT_FALSE(cache->Get(notExistKey, &out));
|
|
}
|
|
|
|
ASSERT_EQ(10, cache->GetCacheMetrics()->cacheHit.get_value());
|
|
ASSERT_EQ(10, cache->GetCacheMetrics()->cacheMiss.get_value());
|
|
for (int i = 0; i < 5; ++i) {
|
|
ASSERT_TRUE(cache->Get(existKey, &out));
|
|
}
|
|
|
|
ASSERT_EQ(15, cache->GetCacheMetrics()->cacheHit.get_value());
|
|
ASSERT_EQ(10, cache->GetCacheMetrics()->cacheMiss.get_value());
|
|
}
|
|
|
|
TEST(CaCheTest, TestCacheGetLast) {
|
|
auto cache = std::make_shared<LRUCache<int, bool>>(
|
|
std::make_shared<CacheMetrics>("LruCache"));
|
|
|
|
for (int i = 0; i < 3; ++i) {
|
|
cache->Put(i, true);
|
|
}
|
|
cache->Put(3, false);
|
|
for (int i = 4; i < 6; ++i) {
|
|
cache->Put(i, true);
|
|
}
|
|
int out;
|
|
cache->GetLast(false, &out);
|
|
ASSERT_EQ(3, out);
|
|
cache->GetLast(true, &out);
|
|
ASSERT_EQ(0, out);
|
|
}
|
|
|
|
TEST(CaCheTest, TestCacheGetLastKV) {
|
|
auto cache = std::make_shared<LRUCache<int, int>>(
|
|
std::make_shared<CacheMetrics>("LruCache"));
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
cache->Put(i, i);
|
|
}
|
|
|
|
int k, v;
|
|
cache->GetLast(&k, &v);
|
|
ASSERT_EQ(0, k);
|
|
ASSERT_EQ(0, v);
|
|
cache->Remove(0);
|
|
cache->GetLast(&k, &v);
|
|
ASSERT_EQ(1, k);
|
|
ASSERT_EQ(1, v);
|
|
}
|
|
bool TestFunction(const int& a) {
|
|
return a > 1;
|
|
}
|
|
TEST(CaCheTest, TestCacheGetLastKVWithFunction) {
|
|
auto cache = std::make_shared<LRUCache<int, int>>(
|
|
std::make_shared<CacheMetrics>("LruCache"));
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
cache->Put(i, i);
|
|
}
|
|
|
|
int k, v;
|
|
cache->GetLast(&k, &v, TestFunction);
|
|
ASSERT_EQ(2, k);
|
|
ASSERT_EQ(2, v);
|
|
cache->Remove(2);
|
|
bool ok = cache->GetLast(&k, &v, TestFunction);
|
|
ASSERT_EQ(false, ok);
|
|
}
|
|
|
|
TEST(SglCaCheTest, TestGetBefore) {
|
|
auto cache = std::make_shared<SglLRUCache<int>>(
|
|
std::make_shared<CacheMetrics>("LruCache"));
|
|
|
|
for (int i = 1; i <= 5; ++i) {
|
|
cache->Put(i);
|
|
}
|
|
int keyBefore;
|
|
for (int i = 1; i < 5; ++i) {
|
|
cache->GetBefore(i, &keyBefore);
|
|
ASSERT_EQ(i + 1, keyBefore);
|
|
}
|
|
}
|
|
|
|
TEST(SglCaCheTest, test_cache_with_capacity_limit) {
|
|
int maxCount = 5;
|
|
auto cache = std::make_shared<SglLRUCache<std::string>>(maxCount,
|
|
std::make_shared<CacheMetrics>("LruCache"));
|
|
|
|
// 1. 测试 put/IsCached
|
|
uint64_t cacheSize = 0;
|
|
for (int i = 1; i <= maxCount; i++) {
|
|
cache->Put(std::to_string(i));
|
|
cacheSize++;
|
|
ASSERT_EQ(i, cache->GetCacheMetrics()->cacheCount.get_value());
|
|
ASSERT_TRUE(cache->IsCached(std::to_string(i)));
|
|
}
|
|
|
|
// 2. 第一个元素被剔出
|
|
cache->Put(std::to_string(11));
|
|
ASSERT_FALSE(cache->IsCached(std::to_string(1)));
|
|
|
|
// 3. 测试删除元素
|
|
// 删除不存在的元素
|
|
cache->Remove("1");
|
|
// 删除list中存在的元素
|
|
cache->Remove("2");
|
|
ASSERT_FALSE(cache->IsCached("2"));
|
|
ASSERT_EQ(maxCount - 1, cache->GetCacheMetrics()->cacheCount.get_value());
|
|
|
|
// 4. 重复put
|
|
cache->Put("4");
|
|
ASSERT_TRUE(cache->IsCached("4"));
|
|
ASSERT_EQ(maxCount - 1, cache->GetCacheMetrics()->cacheCount.get_value());
|
|
}
|
|
|
|
TEST(SglCaCheTest, test_cache_with_capacity_no_limit) {
|
|
auto cache = std::make_shared<SglLRUCache<std::string>>(
|
|
std::make_shared<CacheMetrics>("LruCache"));
|
|
|
|
// 1. 测试 put/IsCached
|
|
std::string res;
|
|
for (int i = 1; i <= 10; i++) {
|
|
std::string eliminated;
|
|
cache->Put(std::to_string(i));
|
|
ASSERT_TRUE(cache->IsCached(std::to_string(i)));
|
|
ASSERT_FALSE(cache->IsCached(std::to_string(100)));
|
|
}
|
|
|
|
// 2. 测试元素删除
|
|
cache->Remove("1");
|
|
ASSERT_FALSE(cache->IsCached("1"));
|
|
}
|
|
|
|
TEST(SglCaCheTest, TestCacheHitAndMissMetric) {
|
|
auto cache = std::make_shared<SglLRUCache<std::string>>(
|
|
std::make_shared<CacheMetrics>("LruCache"));
|
|
ASSERT_EQ(0, cache->GetCacheMetrics()->cacheHit.get_value());
|
|
ASSERT_EQ(0, cache->GetCacheMetrics()->cacheMiss.get_value());
|
|
|
|
std::string existKey = "hello";
|
|
std::string notExistKey = "world";
|
|
cache->Put(existKey);
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
ASSERT_TRUE(cache->IsCached(existKey));
|
|
ASSERT_FALSE(cache->IsCached(notExistKey));
|
|
}
|
|
|
|
ASSERT_EQ(10, cache->GetCacheMetrics()->cacheHit.get_value());
|
|
ASSERT_EQ(10, cache->GetCacheMetrics()->cacheMiss.get_value());
|
|
|
|
for (int i = 0; i < 5; ++i) {
|
|
ASSERT_TRUE(cache->IsCached(existKey));
|
|
}
|
|
|
|
ASSERT_EQ(15, cache->GetCacheMetrics()->cacheHit.get_value());
|
|
ASSERT_EQ(10, cache->GetCacheMetrics()->cacheMiss.get_value());
|
|
}
|
|
|
|
TEST(TimedCaCheTest, test_base) {
|
|
int maxCount = 5;
|
|
int timeOutSec = 0;
|
|
auto cache = std::make_shared<TimedLRUCache<std::string, std::string>>(
|
|
timeOutSec, maxCount, std::make_shared<CacheMetrics>("LruCache"));
|
|
|
|
for (int i = 1; i <= maxCount + 1; i++) {
|
|
std::string eliminated;
|
|
cache->Put(std::to_string(i), std::to_string(i), &eliminated);
|
|
if (i <= maxCount) {
|
|
ASSERT_EQ(i, cache->GetCacheMetrics()->cacheCount.get_value());
|
|
} else {
|
|
ASSERT_EQ(maxCount,
|
|
cache->GetCacheMetrics()->cacheCount.get_value());
|
|
}
|
|
std::string res;
|
|
ASSERT_TRUE(cache->Get(std::to_string(i), &res));
|
|
ASSERT_EQ(std::to_string(i), res);
|
|
}
|
|
|
|
std::string res;
|
|
ASSERT_FALSE(cache->Get(std::to_string(1), &res));
|
|
for (int i = 2; i <= maxCount + 1; i++) {
|
|
ASSERT_TRUE(cache->Get(std::to_string(i), &res));
|
|
ASSERT_EQ(std::to_string(i), res);
|
|
}
|
|
}
|
|
|
|
TEST(TimedCaCheTest, test_timeout) {
|
|
int maxCount = 0;
|
|
int timeOutSec = 1;
|
|
auto cache = std::make_shared<TimedLRUCache<std::string, std::string>>(
|
|
timeOutSec, maxCount, std::make_shared<CacheMetrics>("LruCache"));
|
|
|
|
std::string res;
|
|
ASSERT_FALSE(cache->Get("k", &res));
|
|
ASSERT_EQ(1, cache->GetCacheMetrics()->cacheMiss.get_value());
|
|
cache->Put("k", "v");
|
|
ASSERT_EQ(1, cache->Size());
|
|
ASSERT_EQ(1, cache->GetCacheMetrics()->cacheCount.get_value());
|
|
|
|
ASSERT_TRUE(cache->Get("k", &res));
|
|
ASSERT_EQ(1, cache->GetCacheMetrics()->cacheHit.get_value());
|
|
sleep(1);
|
|
ASSERT_FALSE(cache->Get("k", &res));
|
|
ASSERT_EQ(2, cache->GetCacheMetrics()->cacheMiss.get_value());
|
|
ASSERT_EQ(0, cache->GetCacheMetrics()->cacheCount.get_value());
|
|
ASSERT_EQ(0, cache->GetCacheMetrics()->cacheBytes.get_value());
|
|
ASSERT_EQ(0, cache->Size());
|
|
}
|
|
|
|
} // namespace common
|
|
} // namespace curve
|
|
|
|
|