1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/FishGoddess-cachego

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
lfu_test.go 4.4 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
FishGoddess Отправлено 13.01.2024 15:42 e69b941
// Copyright 2023 FishGoddess. All Rights Reserved.
//
// 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.
package cachego
import (
"math/rand"
"sort"
"strconv"
"testing"
"time"
)
func newTestLFUCache() *lfuCache {
conf := newDefaultConfig()
conf.maxEntries = maxTestEntries
return newLFUCache(conf).(*lfuCache)
}
// go test -v -cover -count=1 -test.cpu=1 -run=^TestLFUCache$
func TestLFUCache(t *testing.T) {
cache := newTestLFUCache()
testCacheImplement(t, cache)
}
// go test -v -cover -count=1 -test.cpu=1 -run=^TestLFUCacheEvict$
func TestLFUCacheEvict(t *testing.T) {
cache := newTestLFUCache()
for i := 0; i < cache.maxEntries*10; i++ {
data := strconv.Itoa(i)
evictedValue := cache.Set(data, data, time.Duration(i)*time.Second)
if i >= cache.maxEntries && evictedValue == nil {
t.Fatalf("i %d >= cache.maxEntries %d && evictedValue == nil", i, cache.maxEntries)
}
}
if cache.Size() != cache.maxEntries {
t.Fatalf("cache.Size() %d != cache.maxEntries %d", cache.Size(), cache.maxEntries)
}
for i := cache.maxEntries*10 - cache.maxEntries; i < cache.maxEntries*10; i++ {
for j := 0; j < i; j++ {
data := strconv.Itoa(i)
cache.Set(data, data, time.Duration(i)*time.Second)
cache.Get(data)
}
}
for i := cache.maxEntries*10 - cache.maxEntries; i < cache.maxEntries*10; i++ {
data := strconv.Itoa(i)
value, ok := cache.Get(data)
if !ok || value.(string) != data {
t.Fatalf("!ok %+v || value.(string) %s != data %s", !ok, value.(string), data)
}
}
i := cache.maxEntries*10 - cache.maxEntries
for cache.itemHeap.Size() > 0 {
item := cache.itemHeap.Pop()
entry := item.Value.(*entry)
data := strconv.Itoa(i)
if entry.key != data || entry.value.(string) != data {
t.Fatalf("entry.key %s != data %s || entry.value.(string) %s != data %s", entry.key, data, entry.value.(string), data)
}
i++
}
}
// go test -v -cover -count=1 -test.cpu=1 -run=^TestLFUCacheEvictSimulate$
func TestLFUCacheEvictSimulate(t *testing.T) {
cache := newTestLFUCache()
for i := 0; i < maxTestEntries; i++ {
data := strconv.Itoa(i)
cache.Set(data, data, NoTTL)
}
maxKeys := 10000
keys := make([]string, 0, maxKeys)
random := rand.New(rand.NewSource(time.Now().Unix()))
for i := 0; i < maxKeys; i++ {
key := strconv.Itoa(random.Intn(maxTestEntries))
keys = append(keys, key)
}
type times struct {
key string
count int
}
counts := make([]times, maxTestEntries)
for _, key := range keys {
cache.Get(key)
i, err := strconv.ParseInt(key, 10, 64)
if err != nil {
t.Fatal(err)
}
counts[i].key = key
counts[i].count++
}
sort.Slice(counts, func(i, j int) bool {
return counts[i].count < counts[j].count
})
t.Log(counts)
expect := make([]string, 0, maxTestEntries)
for i := 0; i < maxTestEntries; i++ {
data := strconv.Itoa(maxTestEntries*10 + i)
expect = append(expect, data)
evictedValue := cache.Set(data, data, NoTTL)
for j := 0; j < maxKeys+i; j++ {
cache.Get(data)
}
if evictedValue.(string) != counts[i].key {
found := false
// Counts may repeat and the sequence may not the same as we think.
for _, count := range counts {
if count.key != evictedValue.(string) {
continue
}
// Count doesn't equal means something wrong happens.
if count.count != counts[i].count {
t.Fatalf("evictedValue.(string) %s != counts[i].key %s", evictedValue.(string), counts[i].key)
}
found = true
break
}
if !found {
t.Fatalf("evictedValue %s not found in counts %+v", evictedValue.(string), counts)
}
}
}
index := 0
for cache.itemHeap.Size() > 0 {
item := cache.itemHeap.Pop()
if item.Value.(*entry).key != expect[index] {
t.Fatalf("item.Value.(*entry).key %s != expect[index] %s", item.Value.(*entry).key, expect[index])
}
if item.Weight() != uint64(maxKeys+index) {
t.Fatalf("item.Weight() %d != uint64(maxKeys + index) %d", item.Weight(), uint64(maxKeys+index))
}
index++
}
}

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/FishGoddess-cachego.git
git@api.gitlife.ru:oschina-mirror/FishGoddess-cachego.git
oschina-mirror
FishGoddess-cachego
FishGoddess-cachego
master