package orchestration import ( "context" "os" "testing" "time" "data-terminal-cloud/internal/cache" ) func TestRedisLeaseCacheRejectsOutOfOrderRefresh(t *testing.T) { redisAddress := os.Getenv("TEST_REDIS_ADDR") if redisAddress == "" { t.Skip("TEST_REDIS_ADDR is not set") } ctx := context.Background() client := cache.Open(redisAddress, "", 0) defer client.Close() prefix := "voice-platform-lease-test-" + time.Now().UTC().Format("150405.000000000") leases, err := NewRedisLeaseCache(client, prefix) if err != nil { t.Fatal(err) } conversationID := "10000000-0000-0000-0000-000000009901" deviceID := "10000000-0000-0000-0000-000000009902" leaseKey := prefix + ":conversation:lease:" + conversationID presenceKey := prefix + ":device:presence:" + deviceID t.Cleanup(func() { client.Del(context.Background(), leaseKey, presenceKey) }) now := time.Now().UTC() if err := leases.Refresh(ctx, LeaseRecord{ ConversationID: conversationID, DeviceID: deviceID, SequenceNo: 10, Status: "ACTIVE", ObservedAt: now, ExpiresAt: now.Add(time.Minute), }); err != nil { t.Fatal(err) } if err := leases.Refresh(ctx, LeaseRecord{ ConversationID: conversationID, DeviceID: deviceID, SequenceNo: 9, Status: "STOPPING", ObservedAt: now.Add(time.Second), ExpiresAt: now.Add(2 * time.Minute), }); err != nil { t.Fatal(err) } values, err := client.HMGet(ctx, leaseKey, "sequence_no", "status").Result() if err != nil { t.Fatal(err) } if values[0] != "10" || values[1] != "ACTIVE" { t.Fatalf("out-of-order heartbeat changed lease: %#v", values) } if online, err := client.HGet(ctx, presenceKey, "online").Result(); err != nil || online != "true" { t.Fatalf("presence online=%q err=%v", online, err) } if err := leases.End(ctx, "", deviceID, now); err == nil { t.Fatal("empty conversation identifier was accepted") } if err := leases.End(ctx, conversationID, deviceID, now.Add(2*time.Second)); err != nil { t.Fatal(err) } if exists, err := client.Exists(ctx, leaseKey).Result(); err != nil || exists != 0 { t.Fatalf("ended lease exists=%d err=%v", exists, err) } values, err = client.HMGet(ctx, presenceKey, "conversation_id", "status").Result() if err != nil || values[0] != "" || values[1] != "idle" { t.Fatalf("ended presence=%#v err=%v", values, err) } }