323 lines
7.1 KiB
Go
323 lines
7.1 KiB
Go
package engine
|
||
|
||
import (
|
||
"context"
|
||
"testing"
|
||
"time"
|
||
)
|
||
|
||
// engineFactory 是一个用于创建引擎实例的函数类型
|
||
type engineFactory func(t *testing.T) Engine
|
||
|
||
// engineTest 包含所有引擎测试用例
|
||
type engineTest struct {
|
||
name string
|
||
factory engineFactory
|
||
}
|
||
|
||
// 运行所有引擎测试
|
||
func runEngineTests(t *testing.T, tests []engineTest) {
|
||
for _, tt := range tests {
|
||
t.Run(tt.name, func(t *testing.T) {
|
||
engine := tt.factory(t)
|
||
|
||
// 测试基本操作
|
||
t.Run("Basic Operations", func(t *testing.T) {
|
||
testBasicOperations(t, engine)
|
||
})
|
||
|
||
// 测试查询功能
|
||
t.Run("Query Operations", func(t *testing.T) {
|
||
testQueryOperations(t, engine)
|
||
})
|
||
|
||
// 测试压缩和清理
|
||
t.Run("Maintenance Operations", func(t *testing.T) {
|
||
testMaintenanceOperations(t, engine)
|
||
})
|
||
|
||
// 测试统计信息
|
||
t.Run("Stats Operations", func(t *testing.T) {
|
||
testStatsOperations(t, engine)
|
||
})
|
||
})
|
||
}
|
||
}
|
||
|
||
// testBasicOperations 测试基本的CRUD操作
|
||
func testBasicOperations(t *testing.T, engine Engine) {
|
||
ctx := context.Background()
|
||
|
||
// 测试打开引擎
|
||
if err := engine.Open(); err != nil {
|
||
t.Fatalf("Failed to open engine: %v", err)
|
||
}
|
||
|
||
// 准备测试数据
|
||
points := []DataPoint{
|
||
{
|
||
Timestamp: time.Now().UnixNano(),
|
||
Value: 42.0,
|
||
Labels: map[string]string{
|
||
"host": "server1",
|
||
"service": "api",
|
||
},
|
||
},
|
||
{
|
||
Timestamp: time.Now().UnixNano(),
|
||
Value: 43.0,
|
||
Labels: map[string]string{
|
||
"host": "server2",
|
||
"service": "api",
|
||
},
|
||
},
|
||
}
|
||
|
||
// 测试写入
|
||
if err := engine.Write(ctx, points); err != nil {
|
||
t.Fatalf("Failed to write points: %v", err)
|
||
}
|
||
|
||
// 测试查询
|
||
query := Query{
|
||
Type: QueryTypeRaw,
|
||
StartTime: time.Now().Add(-1 * time.Hour).UnixNano(),
|
||
EndTime: time.Now().Add(1 * time.Hour).UnixNano(),
|
||
Tags: map[string]string{
|
||
"service": "api",
|
||
},
|
||
}
|
||
|
||
result, err := engine.Query(ctx, query)
|
||
if err != nil {
|
||
t.Fatalf("Failed to query points: %v", err)
|
||
}
|
||
|
||
// 验证查询结果
|
||
if len(result) == 0 {
|
||
t.Error("Query returned no results")
|
||
}
|
||
|
||
// 测试关闭引擎
|
||
if err := engine.Close(); err != nil {
|
||
t.Fatalf("Failed to close engine: %v", err)
|
||
}
|
||
}
|
||
|
||
// testQueryOperations 测试不同类型的查询操作
|
||
func testQueryOperations(t *testing.T, engine Engine) {
|
||
ctx := context.Background()
|
||
|
||
// 打开引擎
|
||
if err := engine.Open(); err != nil {
|
||
t.Fatalf("Failed to open engine: %v", err)
|
||
}
|
||
defer engine.Close()
|
||
|
||
// 准备测试数据
|
||
now := time.Now()
|
||
points := []DataPoint{
|
||
{
|
||
Timestamp: now.Add(-2 * time.Hour).UnixNano(),
|
||
Value: 10.0,
|
||
Labels: map[string]string{
|
||
"host": "server1",
|
||
"app": "test",
|
||
},
|
||
},
|
||
{
|
||
Timestamp: now.Add(-1 * time.Hour).UnixNano(),
|
||
Value: 20.0,
|
||
Labels: map[string]string{
|
||
"host": "server1",
|
||
"app": "test",
|
||
},
|
||
},
|
||
{
|
||
Timestamp: now.UnixNano(),
|
||
Value: 30.0,
|
||
Labels: map[string]string{
|
||
"host": "server1",
|
||
"app": "test",
|
||
},
|
||
},
|
||
}
|
||
|
||
// 写入测试数据
|
||
if err := engine.Write(ctx, points); err != nil {
|
||
t.Fatalf("Failed to write points: %v", err)
|
||
}
|
||
|
||
// 测试最新值查询
|
||
t.Run("Latest Query", func(t *testing.T) {
|
||
query := Query{
|
||
Type: QueryTypeLatest,
|
||
Tags: map[string]string{
|
||
"host": "server1",
|
||
"app": "test",
|
||
},
|
||
}
|
||
|
||
result, err := engine.Query(ctx, query)
|
||
if err != nil {
|
||
t.Fatalf("Failed to query latest points: %v", err)
|
||
}
|
||
|
||
if len(result) != 1 {
|
||
t.Errorf("Expected 1 series result, got %d", len(result))
|
||
}
|
||
|
||
if len(result[0].Points) != 1 {
|
||
t.Errorf("Expected 1 point, got %d", len(result[0].Points))
|
||
}
|
||
|
||
if result[0].Points[0].Value != 30.0 {
|
||
t.Errorf("Expected latest value 30.0, got %f", result[0].Points[0].Value)
|
||
}
|
||
})
|
||
|
||
// 测试聚合查询
|
||
t.Run("Aggregate Query", func(t *testing.T) {
|
||
query := Query{
|
||
Type: QueryTypeAggregate,
|
||
StartTime: now.Add(-3 * time.Hour).UnixNano(),
|
||
EndTime: now.Add(1 * time.Hour).UnixNano(),
|
||
Tags: map[string]string{"app": "test"},
|
||
AggregateType: AggregateTypeAvg,
|
||
}
|
||
|
||
result, err := engine.Query(ctx, query)
|
||
if err != nil {
|
||
t.Fatalf("Failed to query aggregate: %v", err)
|
||
}
|
||
|
||
if len(result) != 1 {
|
||
t.Errorf("Expected 1 series result, got %d", len(result))
|
||
}
|
||
|
||
// 验证平均值
|
||
expectedAvg := 20.0 // (10 + 20 + 30) / 3
|
||
if len(result[0].Points) > 0 && result[0].Points[0].Value != expectedAvg {
|
||
t.Errorf("Expected average value %f, got %f", expectedAvg, result[0].Points[0].Value)
|
||
}
|
||
})
|
||
|
||
// 测试原始数据查询
|
||
t.Run("Raw Query", func(t *testing.T) {
|
||
query := Query{
|
||
Type: QueryTypeRaw,
|
||
StartTime: now.Add(-3 * time.Hour).UnixNano(),
|
||
EndTime: now.Add(1 * time.Hour).UnixNano(),
|
||
Tags: map[string]string{"app": "test"},
|
||
Limit: 10,
|
||
}
|
||
|
||
result, err := engine.Query(ctx, query)
|
||
if err != nil {
|
||
t.Fatalf("Failed to query raw data: %v", err)
|
||
}
|
||
|
||
if len(result) != 1 {
|
||
t.Errorf("Expected 1 series result, got %d", len(result))
|
||
}
|
||
|
||
if len(result[0].Points) != 3 {
|
||
t.Errorf("Expected 3 points, got %d", len(result[0].Points))
|
||
}
|
||
})
|
||
}
|
||
|
||
// testMaintenanceOperations 测试压缩和清理操作
|
||
func testMaintenanceOperations(t *testing.T, engine Engine) {
|
||
// 打开引擎
|
||
if err := engine.Open(); err != nil {
|
||
t.Fatalf("Failed to open engine: %v", err)
|
||
}
|
||
defer engine.Close()
|
||
|
||
// 测试压缩
|
||
if err := engine.Compact(); err != nil {
|
||
t.Errorf("Failed to compact: %v", err)
|
||
}
|
||
|
||
// 测试清理
|
||
if err := engine.Cleanup(); err != nil {
|
||
t.Errorf("Failed to cleanup: %v", err)
|
||
}
|
||
}
|
||
|
||
// testStatsOperations 测试统计信息收集
|
||
func testStatsOperations(t *testing.T, engine Engine) {
|
||
ctx := context.Background()
|
||
|
||
// 打开引擎
|
||
if err := engine.Open(); err != nil {
|
||
t.Fatalf("Failed to open engine: %v", err)
|
||
}
|
||
defer engine.Close()
|
||
beforeStats := engine.Stats()
|
||
// 写入一些数据
|
||
points := []DataPoint{
|
||
{
|
||
Timestamp: time.Now().UnixNano(),
|
||
Value: 42.0,
|
||
Labels: map[string]string{"test": "stats"},
|
||
},
|
||
}
|
||
|
||
if err := engine.Write(ctx, points); err != nil {
|
||
t.Fatalf("Failed to write points: %v", err)
|
||
}
|
||
|
||
// 获取统计信息
|
||
stats := engine.Stats()
|
||
|
||
// 验证统计信息
|
||
if stats.PointsCount-beforeStats.PointsCount != 1 {
|
||
t.Errorf("Expected points count 1, got %d", stats.PointsCount)
|
||
}
|
||
|
||
if stats.LastWriteTime.IsZero() {
|
||
t.Error("LastWriteTime should not be zero")
|
||
}
|
||
}
|
||
|
||
// TestEngines 运行所有引擎的集成测试
|
||
func TestEngines(t *testing.T) {
|
||
tests := []engineTest{
|
||
{
|
||
name: "MockEngine",
|
||
factory: func(t *testing.T) Engine {
|
||
return NewMockEngine()
|
||
},
|
||
},
|
||
// 当实现了Memory和Bolt引擎后,可以添加它们的测试
|
||
/*
|
||
{
|
||
name: "MemoryEngine",
|
||
factory: func(t *testing.T) Engine {
|
||
config := NewMemoryEngineConfig()
|
||
engine, err := NewEngine(config)
|
||
if err != nil {
|
||
t.Fatalf("Failed to create memory engine: %v", err)
|
||
}
|
||
return engine
|
||
},
|
||
},
|
||
{
|
||
name: "BoltEngine",
|
||
factory: func(t *testing.T) Engine {
|
||
config := NewBoltEngineConfig("test.db")
|
||
engine, err := NewEngine(config)
|
||
if err != nil {
|
||
t.Fatalf("Failed to create bolt engine: %v", err)
|
||
}
|
||
return engine
|
||
},
|
||
},
|
||
*/
|
||
}
|
||
|
||
runEngineTests(t, tests)
|
||
}
|