| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- package service
- import (
- "testing"
- "time"
- "github.com/mhsanaei/3x-ui/v3/internal/database"
- "github.com/mhsanaei/3x-ui/v3/internal/database/model"
- "github.com/mhsanaei/3x-ui/v3/internal/xray"
- )
- // TestAutoRenewClients_MultiInbound covers the renew loop across more than one
- // inbound: every expired client with reset>0 must get a fresh future expiry,
- // zeroed usage and re-enabled state, while a non-expiring client is untouched.
- // It also guards the map-lookup refactor of the old quadratic inner loop.
- func TestAutoRenewClients_MultiInbound(t *testing.T) {
- setupBulkDB(t)
- svc := &InboundService{}
- db := database.GetDB()
- past := time.Now().Add(-48 * time.Hour).UnixMilli()
- future := time.Now().Add(365 * 24 * time.Hour).UnixMilli()
- // Two inbounds, two expiring clients each, plus one client that never expires.
- ib1Clients := []model.Client{
- {Email: "a@x", ID: "11111111-1111-1111-1111-111111111111", Enable: false, Reset: 30, ExpiryTime: past},
- {Email: "b@x", ID: "22222222-2222-2222-2222-222222222222", Enable: false, Reset: 30, ExpiryTime: past},
- }
- ib2Clients := []model.Client{
- {Email: "c@x", ID: "33333333-3333-3333-3333-333333333333", Enable: false, Reset: 7, ExpiryTime: past},
- {Email: "keep@x", ID: "44444444-4444-4444-4444-444444444444", Enable: true, Reset: 0, ExpiryTime: future},
- }
- ib1 := mkInbound(t, 30001, model.VLESS, clientsSettings(t, ib1Clients))
- ib2 := mkInbound(t, 30002, model.VLESS, clientsSettings(t, ib2Clients))
- if err := svc.clientService.SyncInbound(nil, ib1.Id, ib1Clients); err != nil {
- t.Fatalf("SyncInbound ib1: %v", err)
- }
- if err := svc.clientService.SyncInbound(nil, ib2.Id, ib2Clients); err != nil {
- t.Fatalf("SyncInbound ib2: %v", err)
- }
- // Seed traffic rows: expired+depleted for the three renewable clients, and a
- // healthy row for keep@x.
- rows := []xray.ClientTraffic{
- {InboundId: ib1.Id, Email: "a@x", Enable: false, Up: 100, Down: 200, Reset: 30, ExpiryTime: past},
- {InboundId: ib1.Id, Email: "b@x", Enable: false, Up: 300, Down: 400, Reset: 30, ExpiryTime: past},
- {InboundId: ib2.Id, Email: "c@x", Enable: false, Up: 500, Down: 600, Reset: 7, ExpiryTime: past},
- {InboundId: ib2.Id, Email: "keep@x", Enable: true, Up: 1, Down: 2, Reset: 0, ExpiryTime: future},
- }
- if err := db.Create(&rows).Error; err != nil {
- t.Fatalf("seed client_traffics: %v", err)
- }
- if _, count, err := svc.autoRenewClients(db); err != nil {
- t.Fatalf("autoRenewClients: %v", err)
- } else if count != 3 {
- t.Fatalf("renewed count = %d, want 3", count)
- }
- now := time.Now().UnixMilli()
- for _, email := range []string{"a@x", "b@x", "c@x"} {
- var row xray.ClientTraffic
- if err := db.Where("email = ?", email).First(&row).Error; err != nil {
- t.Fatalf("read %s: %v", email, err)
- }
- if row.Up != 0 || row.Down != 0 {
- t.Errorf("%s: usage not reset: up=%d down=%d", email, row.Up, row.Down)
- }
- if !row.Enable {
- t.Errorf("%s: not re-enabled", email)
- }
- if row.ExpiryTime <= now {
- t.Errorf("%s: expiry not advanced: got %d, now %d", email, row.ExpiryTime, now)
- }
- }
- // The non-expiring client must be left exactly as seeded.
- var keep xray.ClientTraffic
- if err := db.Where("email = ?", "keep@x").First(&keep).Error; err != nil {
- t.Fatalf("read keep@x: %v", err)
- }
- if keep.Up != 1 || keep.Down != 2 || keep.ExpiryTime != future {
- t.Errorf("keep@x was modified: %+v", keep)
- }
- // The renewed state must also be reflected in the inbound settings JSON.
- reloaded, err := svc.GetInbound(ib1.Id)
- if err != nil {
- t.Fatalf("GetInbound ib1: %v", err)
- }
- cs, err := svc.GetClients(reloaded)
- if err != nil {
- t.Fatalf("GetClients ib1: %v", err)
- }
- for _, c := range cs {
- if !c.Enable {
- t.Errorf("settings client %s still disabled after renew", c.Email)
- }
- if c.ExpiryTime <= now {
- t.Errorf("settings client %s expiry not advanced: %d", c.Email, c.ExpiryTime)
- }
- }
- }
|