Files
sub2api-cn-relay-manager/internal/store/sqlite/import_runs_repo_test.go

172 lines
5.8 KiB
Go

package sqlite
import (
"context"
"reflect"
"testing"
)
func TestRunStateStore(t *testing.T) {
t.Parallel()
ctx := context.Background()
store := openTestDB(t)
run := ImportRun{
RunID: "run-1",
HostID: "host-1",
Mode: "strict",
AccessMode: "subscription",
SubscriptionUsersJSON: `["user-1"]`,
SubscriptionDays: 30,
ProbeAPIKey: "probe-key",
State: "running",
TotalItems: 1,
}
if err := store.ImportRuns().Create(ctx, run); err != nil {
t.Fatalf("ImportRuns().Create() error = %v", err)
}
run.State = "completed_with_warnings"
run.CompletedItems = 1
run.ActiveItems = 1
run.WarningItems = 1
run.FinishedAt = "2026-05-22T12:00:00Z"
if err := store.ImportRuns().Update(ctx, run); err != nil {
t.Fatalf("ImportRuns().Update() error = %v", err)
}
gotRun, err := store.ImportRuns().GetByRunID(ctx, "run-1")
if err != nil {
t.Fatalf("ImportRuns().GetByRunID() error = %v", err)
}
if gotRun.State != "completed_with_warnings" {
t.Fatalf("run.State = %q, want completed_with_warnings", gotRun.State)
}
if gotRun.WarningItems != 1 {
t.Fatalf("run.WarningItems = %d, want 1", gotRun.WarningItems)
}
if gotRun.HostID != "host-1" {
t.Fatalf("run.HostID = %q, want host-1", gotRun.HostID)
}
if gotRun.SubscriptionUsersJSON != `["user-1"]` {
t.Fatalf("run.SubscriptionUsersJSON = %q, want persisted subscription users", gotRun.SubscriptionUsersJSON)
}
if gotRun.SubscriptionDays != 30 {
t.Fatalf("run.SubscriptionDays = %d, want 30", gotRun.SubscriptionDays)
}
if gotRun.ProbeAPIKey != "probe-key" {
t.Fatalf("run.ProbeAPIKey = %q, want probe-key", gotRun.ProbeAPIKey)
}
legacyBatchID := int64(88)
reusedAccountID := int64(321)
channelID := int64(66)
accountID := int64(77)
item := ImportRunItem{
ItemID: "item-1",
RunID: "run-1",
BaseURL: "https://api.deepseek.com/v1",
ProviderID: "api-deepseek-12345678",
APIKeyFingerprint: "fp_abc123",
RequestedModelsJSON: `["kimi 2.6"]`,
RawModelsJSON: `["kimi-k2.6"]`,
NormalizedModelsJSON: `["kimi-k2.6"]`,
CanonicalFamiliesJSON: `["kimi-2.6"]`,
RecommendedModelsJSON: `["kimi-k2.6"]`,
CurrentStage: "confirm",
ConfirmationStatus: "pending",
AccessStatus: "unknown",
MatchedAccountState: "deprecated",
AccountResolution: "reactivated",
ProvisionReused: true,
ReusedFromProviderID: "api-deepseek-87654321",
ReusedFromAccountID: &reusedAccountID,
ChannelID: &channelID,
AccountID: &accountID,
RetryCount: 2,
ConfirmationAttempts: 3,
LastRetryAt: "2026-05-22T12:01:00Z",
NextRetryAt: "2026-05-22T12:02:00Z",
LeaseOwner: "worker-1",
LeaseUntil: "2026-05-22T12:03:00Z",
AdvisoryMessagesJSON: `["warmup"]`,
LastErrorStage: "confirm",
LastError: "no available accounts",
LegacyBatchID: &legacyBatchID,
LegacyProviderID: "legacy-provider",
CapabilityProfileJSON: `{"transport_profile":{"supports_openai_chat_completions":true}}`,
ResolvedSmokeModel: "kimi-k2.6",
}
if err := store.ImportRunItems().Upsert(ctx, item); err != nil {
t.Fatalf("ImportRunItems().Upsert() error = %v", err)
}
gotItem, err := store.ImportRunItems().GetByItemID(ctx, "item-1")
if err != nil {
t.Fatalf("ImportRunItems().GetByItemID() error = %v", err)
}
if gotItem.APIKeyFingerprint != "fp_abc123" {
t.Fatalf("item.APIKeyFingerprint = %q, want fp_abc123", gotItem.APIKeyFingerprint)
}
if gotItem.CanonicalFamiliesJSON != `["kimi-2.6"]` {
t.Fatalf("item.CanonicalFamiliesJSON = %q, want canonical families json", gotItem.CanonicalFamiliesJSON)
}
if gotItem.MatchedAccountState != "deprecated" {
t.Fatalf("item.MatchedAccountState = %q, want deprecated", gotItem.MatchedAccountState)
}
if gotItem.AccountResolution != "reactivated" {
t.Fatalf("item.AccountResolution = %q, want reactivated", gotItem.AccountResolution)
}
if !gotItem.ProvisionReused {
t.Fatal("item.ProvisionReused = false, want true")
}
if gotItem.ReusedFromProviderID != "api-deepseek-87654321" {
t.Fatalf("item.ReusedFromProviderID = %q, want reused provider id", gotItem.ReusedFromProviderID)
}
if gotItem.ReusedFromAccountID == nil || *gotItem.ReusedFromAccountID != reusedAccountID {
t.Fatalf("item.ReusedFromAccountID = %#v, want %d", gotItem.ReusedFromAccountID, reusedAccountID)
}
if gotItem.LeaseOwner != "worker-1" || gotItem.LeaseUntil != "2026-05-22T12:03:00Z" {
t.Fatalf("lease = (%q, %q), want persisted lease fields", gotItem.LeaseOwner, gotItem.LeaseUntil)
}
event := ImportRunItemEvent{
EventID: "evt-1",
RunID: "run-1",
ItemID: "item-1",
EventType: "retry_scheduled",
Stage: "confirm",
Attempt: 2,
Message: "retry after warmup",
PayloadJSON: `{"next_retry_at":"2026-05-22T12:02:00Z"}`,
}
if err := store.ImportRunEvents().Append(ctx, event); err != nil {
t.Fatalf("ImportRunEvents().Append() error = %v", err)
}
events, err := store.ImportRunEvents().ListByItemID(ctx, "item-1")
if err != nil {
t.Fatalf("ImportRunEvents().ListByItemID() error = %v", err)
}
if len(events) != 1 {
t.Fatalf("len(events) = %d, want 1", len(events))
}
if events[0].EventType != "retry_scheduled" {
t.Fatalf("events[0].EventType = %q, want retry_scheduled", events[0].EventType)
}
items, err := store.ImportRunItems().ListByRunID(ctx, "run-1")
if err != nil {
t.Fatalf("ImportRunItems().ListByRunID() error = %v", err)
}
if len(items) != 1 {
t.Fatalf("len(items) = %d, want 1", len(items))
}
if !reflect.DeepEqual(items[0].AdvisoryMessagesJSON, `["warmup"]`) {
t.Fatalf("items[0].AdvisoryMessagesJSON = %q, want advisory json", items[0].AdvisoryMessagesJSON)
}
}