ccpoad / internal /storage /sql /log_test.go
anyalerob's picture
Upload folder using huggingface_hub
2986042 verified
Raw
History Blame Contribute Delete
6.04 kB
package sql_test
import (
"context"
"testing"
"time"
"ccLoad/internal/model"
)
func newJSONTime(t time.Time) model.JSONTime {
return model.JSONTime{Time: t}
}
func TestLog_AddAndList(t *testing.T) {
t.Parallel()
store := newTestStore(t, "logs.db")
ctx := context.Background()
channelID := createTestChannel(t, ctx, store, "log-test-channel")
now := time.Now()
log := &model.LogEntry{
Time: newJSONTime(now),
Model: "gpt-4",
ChannelID: channelID,
StatusCode: 200,
Message: "success",
Duration: 1.5,
IsStreaming: false,
APIKeyUsed: "abcd...efgh",
}
if err := store.AddLog(ctx, log); err != nil {
t.Fatalf("add log: %v", err)
}
// AddLog 方法不返回 ID,不需要检查
since := now.Add(-1 * time.Hour)
logs, err := store.ListLogs(ctx, since, 10, 0, nil)
if err != nil {
t.Fatalf("list logs: %v", err)
}
if len(logs) != 1 {
t.Errorf("expected 1 log, got %d", len(logs))
}
if len(logs) > 0 && logs[0].Model != "gpt-4" {
t.Errorf("model: got %q, want %q", logs[0].Model, "gpt-4")
}
}
func TestLog_BatchAdd(t *testing.T) {
t.Parallel()
store := newTestStore(t, "batch_logs.db")
ctx := context.Background()
channelID := createTestChannel(t, ctx, store, "batch-log-channel")
now := time.Now()
logs := []*model.LogEntry{
{
Time: newJSONTime(now),
Model: "gpt-4",
ChannelID: channelID,
StatusCode: 200,
Message: "success 1",
Duration: 1.0,
APIKeyUsed: "key1...1key",
},
{
Time: newJSONTime(now),
Model: "claude-3",
ChannelID: channelID,
StatusCode: 200,
Message: "success 2",
Duration: 2.0,
APIKeyUsed: "key2...2key",
},
{
Time: newJSONTime(now),
Model: "gpt-4",
ChannelID: channelID,
StatusCode: 500,
Message: "error",
Duration: 0.5,
APIKeyUsed: "key3...3key",
},
}
if err := store.BatchAddLogs(ctx, logs); err != nil {
t.Fatalf("batch add logs: %v", err)
}
// BatchAddLogs 方法不返回 ID,不需要检查
since := now.Add(-1 * time.Hour)
count, err := store.CountLogs(ctx, since, nil)
if err != nil {
t.Fatalf("count logs: %v", err)
}
if count != 3 {
t.Errorf("expected 3 logs, got %d", count)
}
}
func TestLog_ListRange(t *testing.T) {
t.Parallel()
store := newTestStore(t, "range_logs.db")
ctx := context.Background()
channelID := createTestChannel(t, ctx, store, "range-log-channel")
now := time.Now()
logs := []*model.LogEntry{
{
Time: newJSONTime(now.Add(-2 * time.Hour)),
Model: "old-model",
ChannelID: channelID,
StatusCode: 200,
Message: "old log",
Duration: 1.0,
APIKeyUsed: "key1...1key",
},
{
Time: newJSONTime(now.Add(-30 * time.Minute)),
Model: "recent-model",
ChannelID: channelID,
StatusCode: 200,
Message: "recent log",
Duration: 1.0,
APIKeyUsed: "key2...2key",
},
}
if err := store.BatchAddLogs(ctx, logs); err != nil {
t.Fatalf("batch add logs: %v", err)
}
startTime := now.Add(-1 * time.Hour)
endTime := now
rangeLogs, err := store.ListLogsRange(ctx, startTime, endTime, 100, 0, nil)
if err != nil {
t.Fatalf("list logs range: %v", err)
}
if len(rangeLogs) != 1 {
t.Errorf("expected 1 log in range, got %d", len(rangeLogs))
}
if len(rangeLogs) > 0 && rangeLogs[0].Model != "recent-model" {
t.Errorf("model: got %q, want %q", rangeLogs[0].Model, "recent-model")
}
rangeCount, err := store.CountLogsRange(ctx, startTime, endTime, nil)
if err != nil {
t.Fatalf("count logs range: %v", err)
}
if rangeCount != 1 {
t.Errorf("expected 1 log in range count, got %d", rangeCount)
}
}
func TestLog_Pagination(t *testing.T) {
t.Parallel()
store := newTestStore(t, "pagination_logs.db")
ctx := context.Background()
channelID := createTestChannel(t, ctx, store, "pagination-channel")
now := time.Now()
logs := make([]*model.LogEntry, 10)
for i := 0; i < 10; i++ {
logs[i] = &model.LogEntry{
Time: newJSONTime(now),
Model: "gpt-4",
ChannelID: channelID,
StatusCode: 200,
Message: "log " + string(rune('0'+i)),
Duration: float64(i),
APIKeyUsed: "key...key",
}
}
if err := store.BatchAddLogs(ctx, logs); err != nil {
t.Fatalf("batch add logs: %v", err)
}
since := now.Add(-1 * time.Hour)
page1, err := store.ListLogs(ctx, since, 5, 0, nil)
if err != nil {
t.Fatalf("list logs page 1: %v", err)
}
if len(page1) != 5 {
t.Errorf("page 1: expected 5 logs, got %d", len(page1))
}
page2, err := store.ListLogs(ctx, since, 5, 5, nil)
if err != nil {
t.Fatalf("list logs page 2: %v", err)
}
if len(page2) != 5 {
t.Errorf("page 2: expected 5 logs, got %d", len(page2))
}
seen := make(map[int64]struct{}, len(page1))
for _, entry := range page1 {
seen[entry.ID] = struct{}{}
}
for _, entry := range page2 {
if _, ok := seen[entry.ID]; ok {
t.Fatalf("pages should not overlap, overlapping id=%d", entry.ID)
}
}
}
func TestLog_ListRangeWithCount_PreservesZeroCostMultiplier(t *testing.T) {
t.Parallel()
store := newTestStore(t, "logs_zero_multiplier.db")
ctx := context.Background()
channelID := createTestChannel(t, ctx, store, "free-log-channel")
now := time.Now()
if err := store.AddLog(ctx, &model.LogEntry{
Time: newJSONTime(now),
Model: "gpt-5.4-mini",
ChannelID: channelID,
StatusCode: 200,
Message: "success",
Duration: 1.2,
APIKeyUsed: "key...key",
Cost: 0.019,
CostMultiplier: 0,
}); err != nil {
t.Fatalf("add log: %v", err)
}
startTime := now.Add(-1 * time.Minute)
endTime := now.Add(1 * time.Minute)
logs, total, err := store.ListLogsRangeWithCount(ctx, startTime, endTime, 10, 0, nil)
if err != nil {
t.Fatalf("ListLogsRangeWithCount failed: %v", err)
}
if total != 1 {
t.Fatalf("total=%d, want 1", total)
}
if len(logs) != 1 {
t.Fatalf("len(logs)=%d, want 1", len(logs))
}
if logs[0].CostMultiplier != 0 {
t.Fatalf("cost_multiplier=%v, want 0", logs[0].CostMultiplier)
}
}