Files
EdgeNode/internal/utils/kvstore/table_test.go

418 lines
7.3 KiB
Go

// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
package kvstore_test
import (
"fmt"
"github.com/TeaOSLab/EdgeNode/internal/utils/kvstore"
"github.com/TeaOSLab/EdgeNode/internal/utils/testutils"
"github.com/iwind/TeaGo/assert"
"github.com/iwind/TeaGo/types"
"math/rand"
"runtime"
"strconv"
"testing"
"time"
)
func TestTable_Set(t *testing.T) {
store, err := kvstore.OpenStore("test")
if err != nil {
t.Fatal(err)
}
defer func() {
_ = store.Close()
}()
db, err := store.NewDB("TEST_DB")
if err != nil {
t.Fatal(err)
}
table, err := kvstore.NewTable[string]("users", kvstore.NewStringValueEncoder[string]())
if err != nil {
t.Fatal(err)
}
db.AddTable(table)
const originValue = "b12345"
err = table.Set("a", originValue)
if err != nil {
t.Fatal(err)
}
value, err := table.Get("a")
if err != nil {
if kvstore.IsNotFound(err) {
t.Log("not found key")
return
}
t.Fatal(err)
}
t.Log("value:", value)
var a = assert.NewAssertion(t)
a.IsTrue(originValue == value)
}
func TestTable_Get(t *testing.T) {
store, err := kvstore.OpenStore("test")
if err != nil {
t.Fatal(err)
}
defer func() {
_ = store.Close()
}()
db, err := store.NewDB("TEST_DB")
if err != nil {
t.Fatal(err)
}
table, err := kvstore.NewTable[string]("users", kvstore.NewStringValueEncoder[string]())
if err != nil {
t.Fatal(err)
}
db.AddTable(table)
for _, key := range []string{"a", "b", "c"} {
value, getErr := table.Get(key)
if getErr != nil {
if kvstore.IsNotFound(getErr) {
t.Log("not found key", key)
continue
}
t.Fatal(getErr)
}
t.Log(key, "=>", "value:", value)
}
}
func TestTable_Exist(t *testing.T) {
store, err := kvstore.OpenStore("test")
if err != nil {
t.Fatal(err)
}
defer func() {
_ = store.Close()
}()
db, err := store.NewDB("TEST_DB")
if err != nil {
t.Fatal(err)
}
table, err := kvstore.NewTable[string]("users", kvstore.NewStringValueEncoder[string]())
if err != nil {
t.Fatal(err)
}
db.AddTable(table)
for _, key := range []string{"a", "b", "c", "12345"} {
b, checkErr := table.Exist(key)
if checkErr != nil {
t.Fatal(checkErr)
}
t.Log(key, "=>", b)
}
}
func TestTable_Delete(t *testing.T) {
var a = assert.NewAssertion(t)
store, err := kvstore.OpenStore("test")
if err != nil {
t.Fatal(err)
}
defer func() {
_ = store.Close()
}()
db, err := store.NewDB("TEST_DB")
if err != nil {
t.Fatal(err)
}
table, err := kvstore.NewTable[string]("users", kvstore.NewStringValueEncoder[string]())
if err != nil {
t.Fatal(err)
}
db.AddTable(table)
value, err := table.Get("a123")
if err != nil {
if !kvstore.IsNotFound(err) {
t.Fatal(err)
}
} else {
t.Log("old value:", value)
}
err = table.Set("a123", "123456")
if err != nil {
t.Fatal(err)
}
{
value, err = table.Get("a123")
if err != nil {
t.Fatal(err)
}
a.IsTrue(value == "123456")
}
err = table.Delete("a123")
if err != nil {
t.Fatal(err)
}
{
_, err = table.Get("a123")
a.IsTrue(kvstore.IsNotFound(err))
}
}
func TestTable_Delete_Empty(t *testing.T) {
var a = assert.NewAssertion(t)
store, err := kvstore.OpenStore("test")
if err != nil {
t.Fatal(err)
}
defer func() {
_ = store.Close()
}()
db, err := store.NewDB("TEST_DB")
if err != nil {
t.Fatal(err)
}
table, err := kvstore.NewTable[string]("users", kvstore.NewStringValueEncoder[string]())
if err != nil {
t.Fatal(err)
}
db.AddTable(table)
{
err = table.Delete("a1", "a2", "a3", "a4", "")
if err != nil {
t.Fatal(err)
}
}
{
err = table.Delete()
if err != nil {
t.Fatal(err)
}
}
// set new
err = table.Set("a123", "123456")
if err != nil {
t.Fatal(err)
}
// delete again
{
err = table.Delete("a1", "a2", "a3", "a4", "")
if err != nil {
t.Fatal(err)
}
}
{
err = table.Delete()
if err != nil {
t.Fatal(err)
}
}
// read
{
var value string
value, err = table.Get("a123")
if err != nil {
t.Fatal(err)
}
a.IsTrue(value == "123456")
}
}
func TestTable_Count(t *testing.T) {
var table = testOpenStoreTable[*testCachedItem](t, "cache_items", &testCacheItemEncoder[*testCachedItem]{})
defer func() {
_ = testingStore.Close()
}()
var before = time.Now()
count, err := table.Count()
if err != nil {
t.Fatal(err)
}
var costSeconds = time.Since(before).Seconds()
t.Log("count:", count, "cost:", costSeconds*1000, "ms", "qps:", fmt.Sprintf("%.2fM/s", float64(count)/costSeconds/1_000_000))
// watch memory usage
if testutils.IsSingleTesting() {
//time.Sleep(5 * time.Minute)
}
}
func TestTable_Truncate(t *testing.T) {
var table = testOpenStoreTable[*testCachedItem](t, "cache_items", &testCacheItemEncoder[*testCachedItem]{})
defer func() {
_ = testingStore.Close()
}()
var before = time.Now()
err := table.Truncate()
if err != nil {
t.Fatal(err)
}
var costSeconds = time.Since(before).Seconds()
t.Log("cost:", costSeconds*1000, "ms")
t.Log("===after truncate===")
testInspectDB(t)
}
func TestTable_ComposeFieldKey(t *testing.T) {
var a = assert.NewAssertion(t)
var table = testOpenStoreTable[*testCachedItem](t, "cache_items", &testCacheItemEncoder[*testCachedItem]{})
defer func() {
_ = testingStore.Close()
}()
var fieldKeyBytes = table.ComposeFieldKey([]byte("Lily"), "username", []byte("lucy"))
t.Log(string(fieldKeyBytes))
fieldValueBytes, keyValueBytes, err := table.DecodeFieldKey("username", fieldKeyBytes)
if err != nil {
t.Fatal(err)
}
t.Log("field:", string(fieldValueBytes), "key:", string(keyValueBytes))
a.IsTrue(string(fieldValueBytes) == "lucy")
a.IsTrue(string(keyValueBytes) == "Lily")
}
func BenchmarkTable_Set(b *testing.B) {
runtime.GOMAXPROCS(4)
store, err := kvstore.OpenStore("test")
if err != nil {
b.Fatal(err)
}
defer func() {
_ = store.Close()
}()
db, err := store.NewDB("TEST_DB")
if err != nil {
b.Fatal(err)
}
table, err := kvstore.NewTable[uint8]("users", kvstore.NewIntValueEncoder[uint8]())
if err != nil {
b.Fatal(err)
}
db.AddTable(table)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
putErr := table.Set(strconv.Itoa(rand.Int()), 1)
if putErr != nil {
b.Fatal(putErr)
}
}
})
}
func BenchmarkTable_Get(b *testing.B) {
runtime.GOMAXPROCS(4)
store, err := kvstore.OpenStore("test")
if err != nil {
b.Fatal(err)
}
defer func() {
_ = store.Close()
}()
db, err := store.NewDB("TEST_DB")
if err != nil {
b.Fatal(err)
}
table, err := kvstore.NewTable[uint8]("users", kvstore.NewIntValueEncoder[uint8]())
if err != nil {
b.Fatal(err)
}
db.AddTable(table)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, putErr := table.Get(types.String(rand.Int()))
if putErr != nil {
if kvstore.IsNotFound(putErr) {
continue
}
b.Fatal(putErr)
}
}
})
}
/**func BenchmarkTable_NextId(b *testing.B) {
runtime.GOMAXPROCS(4)
store, err := kvstore.OpenStore("test")
if err != nil {
b.Fatal(err)
}
defer func() {
_ = store.Close()
}()
db, err := store.NewDB("TEST_DB")
if err != nil {
b.Fatal(err)
}
table, err := kvstore.NewTable[uint8]("users", kvstore.NewIntValueEncoder[uint8]())
if err != nil {
b.Fatal(err)
}
db.AddTable(table)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, nextErr := table.NextId("a")
if nextErr != nil {
b.Fatal(nextErr)
}
}
})
}
**/